Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
C# Multithreading and Async File IO Guide
1. Mul$threaded
and
Async
Programming
in
C#
+
File
IO
Jussi
Pohjolainen
Tampere
University
of
Applied
Sciences
2. Delegates
• You
can
invoke
a
method
(determined
by
run$me)
from
a
delegate
public delegate int SomeMethod(int x, int y);
Console.WriteLine("Thread is " +
Thread.CurrentThread.ManagedThreadId);
SomeMethod a = new SomeMethod(Sum);
Console.WriteLine( a.Invoke(5,5) );
• It's
possible
to
make
the
invoke
in
separate
thread!
3. Asynchronous
Delegate
• By
using
the
same
delegate,
but
calling
BeginInvoke,
the
method
is
done
in
separate
thread
– public IAsyncResult BeginInvoke(parameters..,
AsyncCallback cb, object state)
– public returnType EndInvoke(IAsyncResult result)
• If
the
method
returns
something,
use
EndInvoke
to
get
the
return
value.
4. using System;
using System.Threading;
public delegate int SomeMethod(int x, int y);
class MyMain
{
public static void Main()
{
SomeMethod a = new SomeMethod(Sum);
Console.WriteLine("Firing Asynchronous method");
// IAsyncResult - Represents the status of an asynchronous operation.
IAsyncResult iftAR = a.BeginInvoke(5, 5, null, null);
Console.WriteLine("Doing some work here!");
int answer = a.EndInvoke(iftAR);
Console.WriteLine(answer);
}
public static int Sum(int x, int y)
{
Console.WriteLine("Thread is " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
return x + y;
}
}
5. Synchronizing
Calling
Thread
• If
we
look
at
this
more
closely
– Console.WriteLine("Firing Asynchronous method");
– IAsyncResult iftAR = a.BeginInvoke(5, 5, null, null);
– Console.WriteLine("Doing some work here!");
– // We are waiting here!
– int answer = a.EndInvoke(iftAR);
• We
realize
that
the
a.EndInvoke
waits
un$l
the
"calcula$on"
is
done
6. using System;
using System.Threading;
public delegate int SomeMethod(int x, int y);
class MyMain
{
public static void Main()
{
SomeMethod a = new SomeMethod(Sum);
Console.WriteLine("Firing Asynchronous method");
IAsyncResult iftAR = a.BeginInvoke(5, 5, null, null);
while(!iftAR.IsCompleted)
{
Console.WriteLine("Doing some work here!");
}
int answer = a.EndInvoke(iftAR);
Console.WriteLine(answer);
}
public static int Sum(int x, int y)
{
Console.WriteLine("Thread is " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
return x + y;
}
}
7. Rid
of
Polling
• Instead
of
polling,
it
would
be
a
good
idea
to
have
a
secondary
thread
to
inform
the
calling
thread
when
the
task
is
finished.
8. using System;
using System.Threading;
public delegate int SomeMethod(int x, int y);
class MyMain
{
private static bool done = false;
public static void Main()
{
SomeMethod a = new SomeMethod(Sum);
Console.WriteLine("Firing Asynchronous method");
IAsyncResult iftAR = a.BeginInvoke(5, 5, new AsyncCallback(Done), null);
while(!done)
{
Console.WriteLine("Doing some work here!");
}
int answer = a.EndInvoke(iftAR);
Console.WriteLine(answer);
}
public static int Sum(int x, int y)
{
Console.WriteLine("Thread is " + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(2000);
return x + y;
}
public static void Done(IAsyncResult result)
{
done = true;
}
}
9. using System;
using System.Threading;
using System.Runtime.Remoting.Messaging;
public delegate int SomeMethod(int x, int y);
class MyMain
{
private static bool done = false;
public static void Main()
{
SomeMethod a = new SomeMethod(Sum);
Console.WriteLine("Firing Asynchronous method");
// Passing custom state data
a.BeginInvoke(5, 5, new AsyncCallback(Done), "Message Sending!");
while(!done)
{
Console.WriteLine("Doing some work here!");
}
}
public static void Done(IAsyncResult iftAR)
{
// IAsyncResult is interface, actual object is AsyncResult
AsyncResult ar = (AsyncResult) iftAR;
// AsyncResult holds the delegate
SomeMethod sm = (SomeMethod) ar.AsyncDelegate;
// Make the call
int answer = sm.EndInvoke(iftAR);
Console.WriteLine(answer);
// Also print the message!
string msg = (string) iftAR.AsyncState;
Console.WriteLine(msg);
done = true;
}
}
11. Threading
Namespace
• Threading
namespace
provides
lot
of
classes
for
crea$ng
threads
– Thread
–
Main
class
for
crea$ng
a
thread
– ThreadStart
–
delegate
used
to
specify
which
method
is
run
under
a
thread
– Timer
–
Mechanism
for
execu$ng
a
method
at
specified
intervals
– Lot
of
locking
mechanisms
12. System.Threading.Thread
Class
• Some
sta$c
members
– CurrentThread
–
get
the
current
thread
– Sleep()
–
Suspend
current
thread
• Some
AZributes
– IsAlive
– Name
– Priority
•
Some
Methods
– Abort()
– Join()
– Start()
– …
13. Ge]ng
Informa$on
About
the
Current
Thread
using System;
using System.Threading;
class MyMain
{
public static void Main()
{
Thread.CurrentThread.Name = "My THREAD!";
Console.WriteLine("Name: ");
Console.WriteLine(Thread.CurrentThread.Name);
Console.WriteLine("IsAlive: ");
Console.WriteLine(Thread.CurrentThread.IsAlive);
Console.WriteLine("Priority: ");
Console.WriteLine(Thread.CurrentThread.Priority);
Console.WriteLine("ThreadState: ");
Console.WriteLine(Thread.CurrentThread.ThreadState);
}
}
14. using System;
using System.Threading;
public class Simple
{
public static void DoThis()
{
int i=0;
while (true)
{
Console.WriteLine("Running in its own thread. " + i);
Thread.Sleep(500);
i++;
}
}
public static void Main()
{
Thread aThread = new Thread(new ThreadStart(DoThis));
aThread.Start();
Thread bThread = new Thread(new ThreadStart(DoThis));
bThread.Start();
}
}
15. using System;
using System.Threading;
public class Simple
{
public static void DoThis(object data)
{
int i=0;
while (i < (int) data)
{
Console.WriteLine("Running in its own thread. " + i);
Thread.Sleep(500);
i++;
}
}
public static void Main()
{
Thread aThread = new Thread(new ParameterizedThreadStart(DoThis));
aThread.Start(10);
}
}
16. About
Locking
• When
mul$ple
threads
access
same
informa$on
-‐>
unstable
data
• Example:
one
bank
account,
two
withdrawals
at
the
same
$me
– 1)
is
there
enough
money?
– 2)
if
true,
withdraw
• We
have
a
problem
if
these
steps
are
done
at
the
same
$me:
1,1,2,2
17. Solu$on
• One
solu$on
is
to
use
lock
keyword
• If
on
thread
holds
a
lock,
others
wait
• lock
is
any
object
• Usage
lock(object){
}
18. Timers
using System;
using System.Threading;
class Hello
{
public static void DoThis(object data)
{
Console.WriteLine("Hello!");
}
public static void Main()
{
TimerCallback timeCB = new TimerCallback(DoThis);
Timer t = new Timer(timeCB, // call back delegate object
null, // Any info to the method
0, // Time before first invocation
1000); // Interval
Console.ReadLine();
}
}
21. Access
UI
from
Thread
• If
a
secondary
thread
aZempt
to
access
a
control
it
did
not
create
=>
run$me
error!
private void Button_Click_2(object sender, RoutedEventArgs e)
{
Thread thread = new Thread(new ThreadStart(ModifyTitle));
thread.Start();
}
// Runtime Exception!
public void ModifyTitle()
{
Title = "Hello World";
}
22. Dispatcher
Class
• Dispatcher
class
allows
you
to
modify
UI
from
secondary
thread
• Read
– hZp://msdn.microsog.com/en-‐us/magazine/
cc163328.aspx
23. private void Button_Click_2(object sender, RoutedEventArgs e)
{
Thread t = new Thread(new ThreadStart(ModifyTitle));
t.Start();
}
public void ModifyTitle()
{
Thread.Sleep(1000);
// Change title to "Hello"
Dispatcher.Invoke(new Action(ChangeTitle));
Thread.Sleep(1000);
// Lambda
Dispatcher.Invoke(() => this.Title = "World");
Thread.Sleep(1000);
Dispatcher.Invoke(() => this.Title = "");
string newTitle = "Hello World!";
for (int i = 0; i < newTitle.Length; i++)
{
Thread.Sleep(100);
Dispatcher.Invoke(() => this.Title += newTitle[i]);
}
}
public void ChangeTitle()
{
this.Title = "Hello";
}
24. Upda$ng
UI
and
Timer
• Timer
calls
certain
method
in
interval
• When
using
Threading.Timer
the
task
is
in
different
thread
– Use
Dispatcher.Invoke
to
manipulate
the
UI
thread
• When
using
Windows.Threading.DispatcherTimer,
the
task
in
in
UI
thread
– If
this
performs
a
$me
consuming
task,
the
UI
will
freeze
26. Aync
Calls
Under
.NET
4.5
• Two
new
keywords
to
simplify
threading
even
more
– async
and
await
• Compiler
will
generate
lot
of
code
when
using
these
keywords
• async
– Method
should
be
called
in
an
asynchronous
manner
automa$cally
• await
– Pause
current
thread
un$l
task
is
complete
27. async
and
await
• In
.NET
4.5,
new
keywords:
async
and
await
• Simplifies
threading,
generates
a
lot
of
code!
• See:
– hZp://blogs.msdn.com/b/pfxteam/archive/
2012/04/12/10293335.aspx
28. namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void Button_Click_1(object sender, RoutedEventArgs e)
{
WebClient wb = new WebClient();
Task<string> result = wb.DownloadStringTaskAsync(new Uri("http://www.tamk.fi/"));
string r = await result;
Contents.Text = r;
}
}
}
30. Overview
• System.IO
namespace
provides
number
of
classes
for
reading
and
wri$ng
• Store
and
retrieve
primi$ve
types
– BinaryReader,
BinaryWriter
• Store
and
retrieve
text
– StreamReader,
StreamWriter
• Buffered
reading
– BufferedStream
• Helper
classes
like
File
(sta$c),
FileInfo
(object
reference
31. Reading
and
Wri$ng
Text
• StreamWriter
and
StreamReader
use
useful
when
need
for
read
or
write
text
• By
default:
Unicode
– Can
be
changed:
pass
System.TextEncoding
object
reference
• Methods
– Write(),
WriteLine()
33. Wri$ng:
Flush
it!
using System;
using System.IO;
class SaveText
{
public static void Main()
{
StreamWriter writer = File.CreateText("./textfile.txt");
writer.WriteLine("Hello World!");
writer.WriteLine("Hello World!");
writer.Flush();
}
}
34. Wri$ng:
Stream
should
be
closed!
using System;
using System.IO;
class SaveText
{
public static void Main()
{
StreamWriter writer = File.CreateText("./textfile.txt");
writer.WriteLine("Hello World!");
writer.WriteLine("Hello World!");
writer.Flush();
writer.Close();
}
}
35. Wri$ng:
Flushing
is
done
when
closing!
using System;
using System.IO;
class SaveText
{
public static void Main()
{
StreamWriter writer = File.CreateText("./textfile.txt");
writer.WriteLine("Hello World!");
writer.WriteLine("Hello World!");
writer.Close();
}
}
36. Wri$ng:
using
using System;
using System.IO;
class ReadText
{
public static void Main()
{
using( StreamWriter writer = File.CreateText("./textfile.txt") )
{
writer.WriteLine("Hello World!");
writer.WriteLine("Hello World!");
}
}
}
37. Reading
Text
using System;
using System.IO;
class ReadText
{
public static void Main()
{
using( StreamReader reader = File.OpenText("./textfile.txt") )
{
string input = null;
while((input = reader.ReadLine()) != null)
{
Console.WriteLine(input);
}
}
}
}
38. Reading
and
Wri$ng
Binary
using System;
using System.IO;
class ReadBinary
{
public static void Main()
{
using( BinaryWriter writer = new BinaryWriter( File.OpenWrite("./test.dat") ) )
{
writer.Write(2.2);
}
using( BinaryReader reader = new BinaryReader( File.OpenRead("./test.dat") ) )
{
Console.WriteLine(reader.ReadDouble());
}
}
}
39. Watching
Files
• Monitor
or
watch
files
using
FileSystemWatcher
class
• Really
easy
to
implement
– Which
folder
are
we
looking?
– Set
up
things
to
listen
– Add
Filters
– Add
Event
Handlers
– Start
listening
40. Example
using System;
using System.IO;
class Watcher
{
public static void Main()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = "/Users/pohjus/Desktop/tuhoa/";
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
watcher.Filter = "*.txt";
watcher.Changed += (object source, FileSystemEventArgs e) => Console.Write("Changed");
watcher.Deleted += (object source, FileSystemEventArgs e) => Console.Write("Deleted");
watcher.EnableRaisingEvents = true;
Console.Read();
}
}
41. Serializable
• Serializa$on?
Store
an
state
of
the
object
into
stream!
• Example:
Store
app
preferences
into
a
file.
Preference
informa$on
are
stored
in
object.
• How?
Mark
a
class
as
Serializable
and
use
classes
to
store
and
open
the
object
• You
can
save
the
object
as
binary
or
xml
(use
XMLSerializer
-‐
class)
42. using
System;
using
System.IO;
using
System.Run$me.Serializa$on.FormaZers.Binary;
[Serializable]
class
Person
{
public
string
Name
{
get;
set;
}
public
int
Age
{
get;
set;
}
}
class
SerializableExample
{
public
sta$c
void
Main()
{
Person
jack
=
new
Person()
{
Name
=
"Jack",
Age
=
20
};
//
Let's
save
jack
as
binary
BinaryFormaZer
binFormat
=
new
BinaryFormaZer();
//
And
in
which
file?
using(FileStream
fs
=
new
FileStream("person.dat",
FileMode.Create))
{
//
Let's
do
it!
binFormat.Serialize(fs,
jack);
}
}
}
43. using
System;
using
System.IO;
using
System.Run$me.Serializa$on.FormaZers.Binary;
[Serializable]
class
Person
{
public
string
Name
{
get;
set;
}
public
int
Age
{
get;
set;
}
}
class
SerializableExample
{
public
sta$c
void
Main()
{
BinaryFormaZer
binFormat
=
new
BinaryFormaZer();
//
Deserialize!
using(FileStream
fs
=
new
FileStream("person.dat",
FileMode.Open))
{
Person
jack2
=
(Person)
binFormat.Deserialize(fs);
Console.WriteLine(jack2.Name);
Console.WriteLine(jack2.Age);
}
}
}
45. WPF
• Windows
Presenta$on
Founda$on
(or
WPF)
is
a
computer-‐sogware
graphical
subsystem
for
rendering
user
interfaces
in
Windows-‐based
applica$ons
• WPF
employs
XAML,
an
XML-‐based
language,
to
define
and
link
various
UI
elements
• See
– hZp://msdn.microsog.com/en-‐us/library/
ms752299.aspx