C # use multithreading to make the software interface more responsive

Source: Internet
Author: User

The response feature of the software interface is an important aspect of determining a software. In general, no matter how wonderful your software functions are, if the software crashes, it will make users feel very annoying and even doubt whether there is a bigger problem in your software.

To improve the interface response features, the best way is to use multiple threads and separate the threads that present the interface. In the past, only C ++ was used to implement multithreading. Now, in the. Net Framework, all languages (including VB) can be used. However, using multithreading is much more troublesome than using a single thread, such as synchronization between threads, sometimes it takes a few weeks for developers to find such errors. Multithreading in Windows Form software has some restrictions.

Next we will introduce the precautions for using multithreading in Windows Form software.

First
First, what operations should I consider using multithreading? In general, the thread responsible for interaction with the user (hereinafter referred to as the UI thread) should be smooth, the use of multithreading should be considered when the API called by the UI thread may cause congestion for more than 30 milliseconds (such as access to ultra-slow peripherals such as CD-ROM, remote calls, etc. Why is it 30 ms? The concept of 30 ms is a lag that can be noticed by the human eye. It is equivalent to the frame stay time in a movie, and the maximum length should not exceed 100 ms.

Second, the most convenient and simple multithreading is to use the thread pool. The easiest way to run code through a thread in the thread pool is to use an asynchronous delegate call. Note that the delegate call is usually completed in synchronization. Use the BeginInvoke method to queue the method to be called to the thread pool for processing, the process of the program will be immediately returned to the caller (this is the UI thread), and the caller will not be blocked.

Taking a look at the example below, we find that it is not very complicated to use the thread pool for asynchronous code execution. Here we use the System. Windows. Forms. MethodInvoker delegate for asynchronous calls. Note that the MethodInvoker delegate does not accept method parameters. If you need to pass parameters to the Asynchronous Method, use another delegate or define it yourself.

Private void StartSomeWorkFromUIThread (){
// The work we need to do is slower than that of the UI thread. Use the following method for asynchronous processing.
MethodInvoker mi = new MethodInvoker (RunsOnWorkerThread); // This is the entry Method
Mi. BeginInvoke (null, null); // This will not block
}

// Slow work is processed in this method, using the thread in the thread pool
Private void RunsOnWorkerThread (){
DoSomethingSlow ();
}

To sum up the above methods, the UI thread is actually: 1. Make a call, 2. Return immediately. The specific running process is ignored, so that the UI thread will not be blocked. This method is very important. We will introduce it in detail below. In addition to the above method, there are other methods to use the thread pool, of course, if you are happy, you can also create your own thread.

Third, to use multithreading in Windows Form, the most important thing to note is that apart from creating the control thread, do not call control members in any other thread (except for a few cases). That is to say, the control belongs to the thread that creates it and cannot be accessed from other threads. This applies to all controls derived from System. Windows. Forms. Control (so it can be said that almost all controls), including the Form Control itself. We can easily draw the conclusion that the child control of the control must be created by the thread of the control to be created, such as a button on a form, such as a form creation thread, therefore, all controls in a window are actually in the same thread. In actual programming, most software practices allow the same thread to take charge of all controls. This is what we call the UI thread. See the following example:

// This is the Label control defined by the UI thread
Private Label lblStatus;
....
// The following method is not executed on the UI thread
Private void RunsOnWorkerThread (){
DoSomethingSlow ();
LblStatus. Text = "Finished! "; // This is incorrect
}

We would like to remind you that many people will use the above methods to access controls not in the same thread (including the author) at the beginning, and in Version 1.0. net Framework does not seem to find any problems, but this is simply wrong. What's worse, programmers will not receive any error prompts here, and they will be cheated at the beginning, other errors will be detected in the future, which is the pain point of Windows Form multi-threaded programming. I tried to spend a lot of time debugging the Splash window that I wrote and suddenly disappeared. The result still failed: During the software guidance process, create a Splash window in another thread to display the welcome information. Then, try to write the guiding status in the main thread directly to the control in the Splash window and start to return OK, however, after a while, the Splash window will disappear.

After understanding this, we should note that sometimes even if the System is not used. threading. thread to explicitly create a Thread. We may also use the BeginInvoke method of asynchronous delegation to implicitly create a Thread (from the Thread pool ), in this thread, you cannot call the members of the Control created by the UI thread.

Fourth, we may feel inconvenient due to the above restrictions. Indeed, when we use a newly created thread to execute some time-consuming operations, how can I know the operation progress and report it to users through the UI? There are many solutions! For example, users who are familiar with multi-thread programming will soon think that we adopt some low-level synchronization methods, and the worker thread will save the state to a synchronization object so that the UI thread can Polling) this object can be fed back to the user. However, this is quite troublesome. In fact, we don't need to do this. The Control class (and its derived class) object has an Invoke method, which is one of the few Members not limited by threads. We mentioned earlier that we should never call a member of a control not created in this thread in any other thread, but also say "only a few exceptions ", this Invoke method is one of the most common cases-the Invoke method can be called from any thread. The following describes the Invoke method.

The parameters of the Invoke method are very simple, a delegate and a parameter table (Optional). The main function of the Invoke method is to help you in the UI thread (that is, to create the control thread) the method specified by the delegate. The Invoke method first checks whether the calling thread (that is, the current thread) is a UI thread. If yes, it directly executes the method pointed to by the delegate. If not, it switches to the UI thread, then execute the delegate pointing method. Regardless of whether the current thread is a UI thread, Invoke is blocked until the execution of the method pointed to by the delegate is completed, and then the call thread is switched back (if needed) to return. Note: when using the Invoke method, the UI thread cannot be in the blocking state. The following MSDN description of the Invoke method:

"There are four methods on the control that can be safely called from any thread: Invoke, BeginInvoke, EndInvoke, and CreateGraphics. For all other method calls, use one of the Call (invoke) Methods to block calls to the control thread.
The delegate can be an EventHandler instance. In this case, the sender parameter will include this control, and the event parameter will include EventArgs. Empty. The delegate can also be a MethodInvoker instance or any other delegate that uses the void parameter list. Calling EventHandler or MethodInvoker delegation is faster than calling other types of delegation ."

Okay. After Invoke is finished, let's talk about BeginInvoke. There is no doubt this is the asynchronous version of Invoke (Invoke is synchronized), but we should not discuss it with the above System. windows. forms. the BeginInvoke in the MethodInvoker delegate is obfuscated. Both use different threads to complete the work, but the BeginInvoke method of the Control always uses the UI thread, while other asynchronous delegate call methods use the threads in the thread pool. Compared with Invoke, it is a little more troublesome to use BeginInvoke, but in that sentence, Asynchronization is better than synchronization, although it is more complicated. For example, a deadlock may occur in the synchronous method: when the worker thread synchronously calls the methods in the UI thread through Invoke, what if the UI thread is waiting for the worker thread to do something? Therefore, the asynchronous method should be used whenever possible.

Next we will use the learned knowledge to rewrite the simple example above:

// This is the Label control defined by the UI thread
Private Label lblStatus;
....
// The following method is not executed on the UI thread
Private void RunsOnWorkerThread (){
DoSomethingSlow ();
// Do UI update on UI thread
Object [] pList = {this, System. EventArgs. Empty };
LblStatus. BeginInvoke (
New System. EventHandler (UpdateUI), pList );
}
....

// Switch back to the UI thread execution entry
Private void UpdateUI (object o, System. EventArgs e ){
// Now there is no problem. With Invoke, the thread always returns to the UI thread, so we can safely and boldly call the control members.
LblStatus. Text = "Finished! ";
}

Fifth, we will not repeat the many articles on multithreading programming that require consideration of synchronization between threads, deadlocks, and contention conditions.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.