1 / 48

Asynchronous Programming in C# 5.0

Asynchronous Programming in C# 5.0. Muzaffer DOĞAN Anadolu University Computer Engineering Dept. My Research Area. Signal Processing Image Processing Wavelets. Outline. Traditional multi-threaded programming The problems in threads C#’s solution An example Conclusion.

waneta
Download Presentation

Asynchronous Programming in C# 5.0

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Asynchronous Programming in C# 5.0 Muzaffer DOĞAN Anadolu University Computer Engineering Dept.

  2. My Research Area • Signal Processing • Image Processing • Wavelets Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  3. Outline • Traditional multi-threaded programming • The problems in threads • C#’s solution • An example • Conclusion Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  4. Why Parallel Processing? • Responsive user interface • Allowing multiple user requests • ASP.NET, web services, etc. • Parallel programming Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  5. Threading • Thread: Execution path that can proceed independently of others • Single-threaded programs: Just one thread runs in the process • Multithreaded programs: Multiple thread run in the process • All threads share the same execution environment (memory) Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  6. Using Threads in C# • Import the namespace System.Threading • Create a Threadobject using a ThreadStartdelegate • Call the thread by its Startmethod • If you want to wait until the end of the thread, use its Joinmethod • If you want to delay a thread, use the static Thread.Sleepmethod Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  7. using System; using System.Threading; class ThreadTest { static void Main() { Thread t = new Thread(WriteY); // Kick off a new thread t.Start(); // running WriteY() // Simultaneously, do something on the main thread. for (inti = 0; i < 1000; i++) Console.Write("x"); } static void WriteY() { for (inti = 0; i < 1000; i++) Console.Write("y"); } } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  8. The Output xxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyy yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy yyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ... Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  9. The Mechanism Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  10. Local Variables staticvoid Main() { new Thread (Go).Start(); // Call Go() on a new thread Go(); // Call Go() on the main thread } staticvoidGo() { // Declare and use a local variable - 'cycles' for (int cycles = 0; cycles < 5; cycles++) Console.Write('?'); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  11. The Output ?????????? Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  12. Shared Variables classThreadTest{ static bool_done; // Shared between all threads staticvoid Main(){ newThread (Go).Start(); Go(); } staticvoidGo(){ if (!_done) { _done = true; Console.WriteLine ("Done"); } } } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  13. The Output • The output will be a single Done text printed on the screen • The main thread changes the value of _done variable first • The new thread gets the changed value of _done and prints nothing Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  14. A small change… classThreadTest{ static bool_done; // Shared between all threads staticvoid Main(){ newThread (Go).Start(); Go(); } staticvoidGo(){ if (!_done) { Console.WriteLine ("Done"); _done = true;} } } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  15. The Output • Probability of printing two Done texts increases because the Console.WriteLine method may take a long time • The main thread may get the _done variable first as false • While the main thread prints the text Done on the screen, the second thread may take the _done variable with the value false • In this case, twoDone texts are printed • If the main thread changes the value of _done before the second thread reads its value, only oneDone is printed on the screen • This example introduces the Thread Safety (or lack of it) Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  16. Thread Safety • If two threads read or write a memory space concurrently without any errors, it’s called thread safety • Safety of the .NET Framework methods are documented in their help pages • Locking may be a solution for the thread safety Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  17. classThreadSafe{ staticbool _done; static readonly object _locker = new object(); staticvoid Main(){ newThread (Go).Start(); Go(); } staticvoidGo(){ lock(_locker){ if (!_done) { Console.WriteLine ("Done"); _done = true; } } } } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  18. The Output Done Done Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  19. Passing Data to a Thread • The easiest way is using lambda expressions • Lambda expressions can be thought as internally written functions • Lambda expressions didn’t exist prior to C# 3.0 • Any number of data can be passed • The second way is to use the Thread’s Start method • Only one data can be passed as an object type • Type casting is required in the function • More than one data can be passed in a struct element Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  20. 1) Using Lambda Expression staticvoid Main() { Thread t = newThread ( () => Print ("Hellofrom t!") ); t.Start(); } staticvoidPrint (stringmessage) { Console.WriteLine (message); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  21. 2) Using Thread’s Start Method staticvoid Main(){ Threadt = newThread (Print); t.Start("Hellofrom t!"); } staticvoidPrint (objectmessageObj){ stringmessage = (string)messageObj; Console.WriteLine(message); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  22. Captured Variables for (int i = 0; i < 10; i++) { newThread (() => Console.Write (i)).Start(); } • The output is nondeterministic! Here’s a typical result: • 0223557799 Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  23. Solution • Using a temporary variable solves the problem: for (int i = 0; i < 10; i++) { inttemp = i; new Thread (() => Console.Write (temp)).Start(); } • One of the possible outputs: 0143256789 Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  24. Exception Handling • If an exception occurs in a thread, it can’t be detected in the main block: publicstaticvoid Main(){ try{ newThread (Go).Start(); } catch(Exceptionex){ // We'llneverget here! Console.WriteLine("Exception!"); } } staticvoidGo() { thrownull; } // NullReferenceException Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  25. Solution • Move the exception handling into the thread function • Difficult to code! • If exception is not handled, the program crushes! • Handling exceptions at higher levels would be better! Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  26. Signaling • In a Windows Forms application, all events are controlled by the main thread, namely, UI thread • If a long operation works, the UI becomes unresponsive • You can execute the long operation in a separate thread • At the end of the worker thread, you need to send a signal to the UI thread so that it displays the result • The UI thread can be signaled with the methods BeginInvokeand Invoke • The difference is that the Invoke method blocks the worker thread until the invoked method in the UI thread ends Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  27. Unresponsive UI private void Button1_Click(object sender, EventArgs e) { this.Text = "A long operation has started..."; DoWork(); this.Text = "Completed!"; } privatevoidDoWork() { Thread.Sleep(3000);// Unresponsive UI! } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  28. Make it responsive! private void Button1_Click(object sender, EventArgs e) { this.Text = "A long operation has started..."; Thread t = new Thread(DoWork); t.Start(); } privatevoidDoWork() { Thread.Sleep(3000); this.Text = "Completed!"; } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  29. Signaling UI Thread private void Button1_Click(object sender, EventArgs e){ this.Text= "A long operation has started..."; newThread(DoWork).Start(); } privatevoidDoWork(){ Thread.Sleep(3000); BeginInvoke(newEventHandler(Completed)); } private void Completed(object sender, EventArgs e) { this.Text = "Completed!"; } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  30. Signaling by a Lambda Expression private void Button1_Click(object sender, EventArgs e){ this.Text= "A long operation has started..."; newThread(DoWork).Start(); } private void DoWork() { Thread.Sleep(3000); Action action= () => this.Text = "Completed!"; BeginInvoke(action); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  31. Summary of Problems • Accessing a shared variable • Passing data to a thread • Exception handling • Signaling (or continuation) Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  32. Solution • Asynchronous programming! • Write your methods synchronously • Replace synchronous method calls with asynchronous method calls, and await them. • Upgrade your asynchronous methods’ return types to Task or Task<TResult> so that they’re awaitable. Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  33. private asyncvoid Button1_Click(object sender, EventArgs e) { this.Text = "A long operation has started..."; awaitDoWork(); this.Text = "Completed!"; } privateTaskDoWork() { return Task.Run(() => Thread.Sleep(3000)); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  34. private void asyncButton1_Click(object sender, EventArgs e) { this.Text = "A long operation has started..."; awaitDoWork(); this.Text = "Completed!"; } privateasyncTaskDoWork() { awaitTask.Delay(3000); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  35. private void asyncButton1_Click(object sender, EventArgs e) { this.Text = "A long operation has started..."; awaitTask.Delay(3000); this.Text = "Completed!"; } Continuation problem is automatically solved! Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  36. Lambda Expressions can also be used private void asyncButton1_Click(object sender, EventArgs e) { this.Text = "A long operation has started..."; awaitTask.Run(() => Thread.Sleep(3000)); this.Text = "Completed!"; } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  37. Passing Data – Synchronous Version staticvoid Main(string[] args) { for (int i = 0; i < 10; i++) { Print(i); } } staticvoidPrint(intnum) { Console.Write(num); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  38. Passing Data – Asynchronous Version staticvoid Main(string[] args){ for (int i = 0; i < 10; i++) { Print(i); } Thread.Sleep(3000); // Wait until all threads finish } staticasyncvoidPrint(intnum){ awaitTask.Run(() => Console.Write(num)); } // One of the possible outputs: 0143256789 Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  39. Exception Handling private async void Button1_Click(object sender, EventArgs e) { try { awaitDoWork(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private Task DoWork() { return Task.Run(() => { Thread.Sleep(3000); throw new NullReferenceException(); }); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  40. Summing up Array Elements • Let’s create an array and compute the sum of its elements by dividing the array into two • Each part will be summed by a separate thread Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  41. Synchronous Solution private int[] A = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; privateintSum(int start, intlength){ intsum = 0; for (int i = start; i < start + length; i++){ sum+= A[i]; } returnsum; } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  42. Synchronous Solution private void Button1_Click(object sender, EventArgs e) { int sum1 = Sum(0, 5); intsum2 = Sum(5, 5); int sum = sum1 + sum2; MessageBox.Show(sum.ToString()); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  43. Asynchronous Solution privateTask<int>Sum(int start, intlength){ returnTask.Run(() => { intsum = 0; for (int i = start; i < start + length; i++) { sum += A[i]; } returnsum; }); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  44. Asynchronous Solution private async void Button1_Click(object sender, EventArgs e) { int sum1 = await Sum(0, 5); int sum2 = await Sum(5, 5); int sum = sum1 + sum2; MessageBox.Show(sum.ToString()); } Function calls are not parallel! Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  45. Solution: WhenAll private asyncvoid Button1_Click(object sender, EventArgs e) { int[] sums = await Task.WhenAll( Sum(0, 5), Sum(5, 5)); intsum = sums[0] + sums[1]; MessageBox.Show(sum.ToString()); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  46. WhenAny private asyncvoid Button1_Click(object sender, EventArgs e) { Task<int> winner = await Task.WhenAny( Sum(0, 5), Sum(5, 5)); int sum = winner.Result; MessageBox.Show(sum.ToString()); } Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  47. Conclusion • Asynchoronous Programming support of C# • simplifies continuation • simplifies exception handling • simplifies multi-threaded programming • simplifies thread-safety • simplifies passing data to a thread • introduces awaitablefunctions • but requires some experience Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

  48. Thank you and questions… Muzaffer Doğan - Comp. Eng. Dept., Anadolu University, Eskişehir, Turkey

More Related