[C #] entering the asynchronous programming world,
Enter the world of asynchronous programming-Execute asynchronous operations in WinForm
[Humble] Reverse bone Zi [original address] http://www.cnblogs.com/liqingwen/p/5877042.html order
This is the third article after "getting started with async/await asynchronous programming" and "going into the world of asynchronous programming-analyzing asynchronous methods. This section describes how to perform asynchronous operations in WinForm.
Directory
- Perform asynchronous operations in WinForm
- Use asynchronous Lambda expressions in WinForm
- A complete WinForm Program
- Another Asynchronous Method-BackgroundWorker class
1. Perform asynchronous operations in the WinForm Program
The following is an example of the form to demonstrate the following operations-click the button:
① Disable the button and change the label content to "Doing" (indicating that the tag is being executed );
② The thread is suspended for 3 seconds (simulating time-consuming operations );
③ Enable the button to change the label content to "Complete" (indicating that the execution is Complete ).
1 public partial class Form1 : Form 2 { 3 public Form1() 4 { 5 InitializeComponent(); 6 } 7 8 private void btnDo_Click(object sender, EventArgs e) 9 {10 btnDo.Enabled = false;11 lblText.Text = @"Doing";12 13 Thread.Sleep(3000);14 15 btnDo.Enabled = true;16 lblText.Text = @"Complete";17 }18 }
However, the execution result is:
Figure 1-1
[Detected problems]
① Doesn't seem to be "Doing "?
2. Why can't I get stuck while dragging the window?
③ After 3 seconds, the system suddenly changes to the desired position?
④ Does the text change to "Complete" at the same time "?
[Analysis] GUI program design requires that all the display changes must be completed in the main GUI thread, such as click events and move forms. Messages are implemented through messages in a Windows program. messages are placed in the message queue managed by the message pump. When you Click the button, the Click message of the button is placed in the message queue. The message pump removes the message from the queue and starts to process the code of the click event, that is, the code of the btnDo_Click event.
The btnDo_Click event puts messages that trigger behavior into the queue. However, messages cannot be executed until the btnDo_Click time processing program completely exits (the thread suspends 3 seconds ago. (3 seconds later) then all the actions happened, but the speed was too fast to be identified by the naked eye, so no tag was found to be changed to "Doing ".
Figure 1-2 Click Event
Figure 1-3 specific execution process of click events
Now we add the async/await feature.
1 public partial class Form1 : Form 2 { 3 public Form1() 4 { 5 InitializeComponent(); 6 } 7 8 private async void btnDo_Click(object sender, EventArgs e) 9 {10 btnDo.Enabled = false;11 lblText.Text = @"Doing";12 13 await Task.Delay(3000);14 15 btnDo.Enabled = true;16 lblText.Text = @"Complete";17 }18 }
Figure 1-4
Now, it is the expected effect.
[Analysis] The btnDo_Click event handler first pushes the first two messages into the queue, and then removes itself from the processor. After 3 seconds (wait until the idle Task is completed. delay) and then press itself into the queue. In this way, the response can be maintained and all messages can be processed within the time when the thread is suspended.
1.1 Task. Yield
The Task. Yield method creates an awaitable that is returned immediately. Wait for a Yield to allow the Asynchronous Method to return the call method while executing the subsequent part. It can be understood as leaving the current message queue and returning to the end of the queue, so that the CPU has time to process other tasks.
1 class Program 2 {3 static void Main (string [] args) 4 {5 const int num = 1000000; 6 var t = DoStuff. yield1000 (num); 7 8 Loop (num/10); 9 Loop (num/10); 10 Loop (num/10); 11 12 Console. writeLine ($ "Sum: {t. result} "); 13 14 Console. read (); 15} 16 17 /// <summary> 18 /// loop 19 /// </summary> 20 /// <param name = "num"> </param> 21 private static void Loop (int num) 22 {23 for (var I = 0; I <num; I ++ ); 24} 25} 26 27 internal static class DoStuff28 {29 public static async Task <int> Yield1000 (int n) 30 {31 var sum = 0; 32 for (int I = 0; I <n; I ++) 33 {34 sum + = I; 35 if (I % 1000 = 0) 36 {37 await Task. yield (); // create an asynchronous waiting task that generates the current context 38} 39} 40 41 return sum; 42} 43}
Figure 1.1-1
The above code calls the Task. Yield method every 1000 cycles to create a waiting Task, so that the processor has time to process other tasks. This method is useful in GUI programs.
Ii. Use asynchronous Lambda expressions in WinForm
Change the Click Event of the window program.
1 public partial class Form1: Form 2 {3 public Form1 () 4 {5 InitializeComponent (); 6 7 // async (sender, e) asynchronous expression 8 btnDo. click + = async (sender, e) => 9 {10 Do (false, "Doing"); 11 12 await Task. delay (3000); 13 14 Do (true, "Finished"); 15}; 16} 17 18 private void Do (bool isEnable, string text) 19 {20 btnDo. enabled = isEnable; 21 lblText. text = text; 22} 23}
The original formula, the familiar taste, the original window, And the meaning.
Figure 2-1
3. A complete WinForm Program
Now the progress bar and the cancel button are added based on the original one.
1 public partial class Form1: Form 2 {3 private CancellationTokenSource _ source; 4 private CancellationToken _ token; 5 6 public Form1 () 7 {8 InitializeComponent (); 9} 10 11 /// <summary> 12 // Do button event 13 /// </summary> 14 /// <param name = "sender"> </param> 15 // <param name = "e"> </param> 16 private async void btnDo_Click (object sender, eventArgs e) 17 {18 btnDo. enabled = false; 19 20 _ source = new Canc EllationTokenSource (); 21 _ token = _ source. token; 22 23 var completedPercent = 0; // percentage of completion 24 const int time = 10; // number of cycles 25 const int timePercent = 100/time; // The Progress value added to the progress bar is 26 27 for (var I = 0; I <time; I ++) 28 {29 if (_ token. isCancellationRequested) 30 {31 break; 32} 33 34 try35 {36 await Task. delay (500, _ token); 37 completedPercent = (I + 1) * timePercent; 38} 39 catch (Exception) 40 {41 completedPercen T = I * timePercent; 42} 43 finally44 {45 progressBar. Value = completedPercent; 46} 47} 48 49 var msg = _ token. IsCancellationRequested? $ "Progress: {completedPercent} % canceled! ": $" Completed "; 50 51 MessageBox. show (msg, @ ""); 52 53 progressBar. value = 0; 54 InitTool (); 55} 56 57 // <summary> 58 // initialize the form tool control 59 // </summary> 60 private void InitTool () 61 {62 progressBar. value = 0; 63 btnDo. enabled = true; 64 btnCancel. enabled = true; 65} 66 67 // <summary> 68 // cancel event 69 // </summary> 70 // <param name = "sender"> </param> 71 // <param name = "e"> </param> 72 private void btnCancel_Click (object sender, eventArgs e) 73 {74 if (btnDo. enabled) return; 75 76 btnCancel. enabled = false; 77 _ source. cancel (); 78} 79}
Figure 3-1
4. Another Asynchronous Method-BackgroundWorker class
Unlike async/await, you may need an additional thread to complete a task in the background and communicate with the main thread from time to time. In this case, you need to use the BackgroundWorker class. It is mainly used for GUI programs.
The words in the book are far less than a simple example.
1 public partial class Form2: Form 2 {3 private readonly BackgroundWorker _ worker = new BackgroundWorker (); 4 5 public Form2 () 6 {7 InitializeComponent (); 8 9 // set the BackgroundWorker attribute 10_worker. workerReportsProgress = true; // whether to report progress update 11_worker. workersuppscanscancellation = true; // whether to asynchronously cancel 12 13 // the handler that connects to the BackgroundWorker object 14_worker. doWork + = _ worker_DoWork; // triggered when the background operation is started, that is, the BackgroundWorker is called. R The 15_worker is triggered when unWorkerAsync is enabled. progressChanged + = _ worker_ProgressChanged; // call BackgroundWorker. reportProgress (System. int32) triggers 16 _ worker. runWorkerCompleted + = _ worker_RunWorkerCompleted; // triggered 17} 18 19 when the background operation is completed, canceled, or caused an exception // <summary> 20 // when the background operation is completed, canceled, or caused an exception 21 // </summary> 22 // <param name = "sender"> </param> 23 // <param name = "e"> </param> 24 private void _ worker_RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e) 25 {26 MessageBox. Show (e. Cancelled? $ @ "The process has been canceled: {progressBar. value} % ": $ @" process execution completed: {progressBar. value} % "); 27 progressBar. value = 0; 28} 29 30 // <summary> 31 // call BackgroundWorker. reportProgress (System. int32) 32 // </summary> 33 // <param name = "sender"> </param> 34 // <param name = "e"> </param> 35 private void _ worker_ProgressChanged (object sender, progressChangedEventArgs e) 36 {37 progressBar. value = e. progressPercentage; // progress percentage of asynchronous tasks Than 38} 39 40 // <summary> 41 // start to execute background operation trigger, that is, call BackgroundWorker. runWorkerAsync: 42 // </summary> 43 // <param name = "sender"> </param> 44 // <param name = "e"> </ param> 45 private static void _ worker_DoWork (object sender, doWorkEventArgs e) 46 {47 var worker = sender as BackgroundWorker; 48 if (worker = null) 49 {50 return; 51} 52 53 for (var I = 0; I <10; I ++) 54 {55 // determine whether the program has requested to cancel the background operation 56 if (worker. cance LlationPending) 57 {58 e. cancel = true; 59 break; 60} 61 62 worker. reportProgress (I + 1) * 10); // triggers BackgroundWorker. progressChanged event 63 Thread. sleep (250); // thread suspension 250 ms 64} 65} 66 67 private void btnDo_Click (object sender, EventArgs e) 68 {69 // determine whether the BackgroundWorker is performing an asynchronous operation 70 if (! _ Worker. isBusy) 71 {72 _ worker. runWorkerAsync (); // start to execute background Operations 73} 74} 75 76 private void btnCancel_Click (object sender, EventArgs e) 77 {78 _ worker. cancelAsync (); // request to cancel pending background operations 79} 80}
Figure 4-1
Portal
Entry: entering the world of asynchronous programming-getting started with async/await asynchronous programming
Article 1: going into the world of asynchronous programming-analyzing asynchronous methods (I)-going into the world of asynchronous programming-analyzing asynchronous methods (II)
[Reference] Illustrated C #2012