The response characteristic of the software interface is a very important aspect of judging a software. In general, no matter how wonderful your software function is done, if the software has a little dead machine, it will make users feel annoying, and even doubt whether there is a bigger problem in your software.
To improve the response characteristics of the interface, the best way is to use multithreading and independently of the thread of the presentation interface. Previously, only multi-thread features that c can implement, 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 problems between threads, it is very easy to make mistakes, and sometimes this error will develop people to spend a few weeks to find. There are some restrictions in using multi-threads in Windows Form software.
Below we will introduce you to your questions that you should pay attention to in Windows Form software.
first
First, what kind of operation needs to consider using multithreaded? The total one is, responsible for interacting with the user (hereinafter referred to as the UI thread) should remain smoothly, when the UI thread calls call the API that can cause the blocking time of more than 30 milliseconds (such as access to the CD-ROM and other speeds, Remote calls, etc.) should consider using multithreading. Why is it 30 milliseconds? The concept of 30 milliseconds is a hysteresis that the human eye can be perceived, which is about 100 milliseconds that are approximately equal to one frame in the movie.
Second, the most convenient and simple multi-threading is using a thread pool. The easiest way to run code through threads in the thread is to use asynchronous commission. Note that the delegation is usually completed synchronously. Use the BeginInvoke method so that you can queue the method you want to call to the thread pool, and the process of the program will return to the caller immediately (here is a UI thread), and call The party will not block blocking.
Take a look at the examples below. We will find that the asynchronous execution code to use the thread pool is not very complicated. Here we use System.Windows.Forms.MethodInvoker to delegate asynchronous calls. Note that the MethodInvoker delegate does not accept method parameters. If you need to pass parameters to the way asynchronous execution, use other delegates, or you need your own definition.
Private void startsomeworkfromsuithread () {// We have to do the work relative to the UI thread, and use the following method asynchronously processed MethodInvoker Mi = New MethodInvoker (RunsonWorkerthRead); // This is the entry method m.Beginvoke (Null, NULL); // This will not block}
// Slow work in this method, use the thread in the thread PRIVATE VOID RUNSONWORKERTHREAD () {DOSMETHINGSLOW ();}
Increte the above method, in practice for the UI thread is: 1. Send call, 2, return immediately, the specific operation process is ignored, so that the UI thread will not be blocked. This method is very important, and we will introduce it deeply. In addition to the above methods, there are other methods of using thread pools, of course, if you are happy, you can create threads yourself.
Third, in Windows Form uses multithreaded, the most important consideration is that in addition to creating controls threads, do not call members of the control in any other thread (only exceptional exceptions), that is, controls It is a thread that is created and cannot be accessed from other threads. This is suitable for all controls derived from System.Windows.Forms.Control (so it can be said to be almost all controls), including the FORM control itself. For the other words, we can easily draw such conclusions, and the control of the child must be created by the thread that creates controls, such as a button on a form, such as creating a thread that creates a form, so all controls in a window actually Alike among the same thread. When actually programming, most software practices are all controls that the same thread is responsible for all controls, which is the UI thread we said. Look at the example below: // This is the Label control private labl lblstatus defined by the UI thread; .... // The following method does not execute private void RunsonWorkerthread () {dosomethingslow (); lblstatus.text = "Finished! "; // this is wrong}
We must especially remind everyone that many people will use the above methods to access the controls in the same thread (including the author), and there seems to have no problems on the 1.0 version .NET framework, but this is wrong What is even worse is that the programmer will not get any error here. At the beginning, it is deceived, and then it will be unique to find other mistakes, which is the pain of Windows Form multithreaded programming. The author tried to spend a lot of time to debug's question that the Splash window she wrote suddenly disappeared. The result was still failed: the author created a Splash window in the boot process of the software to display the welcome information, and then try to put the master In the state, the state is directly written directly to the control on the Splash window, starting OK, but after a while, the Splash window will disappear.
Understand this, we should pay attention, sometimes even if you don't have a thread with system.threading.thread, we may also implicitly created threads (from thread pool) because of the BeginInvoke method of asynchronous entrustment. In this thread, the members of the control created by the UI thread cannot be invoked.
Fourth, due to the above constituations, we may feel very inconvenient, indeed, how to know how the operation progress is made and reflected by the UI when we use a newly created thread to perform some time-speaking operations? Work more! For example, familiar multithreading programming will soon think of it, we use some low-level synchronization methods, worker threads save the status into a synchronization object, allowing the UI thread polling (polling) the object and feedback to the user. However, this is still very troublesome. Don't do this, the Control class (and its school) object has an invoke method, which is one of several members who are not limited by thread. As mentioned earlier, I will definitely do not call a member of the control created by the non-thread in any other thread, I also said that "only an exceptional case exception", this Invoke method is one of the extremes of the extreme situation ---- Invoke method can Call from any thread. Let's explain the Invoke method.
The parameters of the Invoke method are very simple, a delegate, a parameter table (optional), and the main function of the Invoke method is to help you raise the method specified by the commission in the UI thread (ie the thread that creates controls). Invoke method first checks the calling thread (ie the current thread) is not a UI thread. If so, execute the principal-to-way method, if not, it will switch to the UI thread, and then perform the principal-to-point method. Regardless of the current thread is not a UI thread, INVOKE is blocked until the method of delegate points is performed, and then switch back to the calling thread (if needed), return. Note that the UI thread cannot be in the blocking state when using the Invoke method. The following MSDN's instructions about the Invoke method: "There are four ways on the control to call any thread: Invoke, Beginvoke, EndInvoke and Creategraphics. For all other methods, you should use one of the invoke method. Send the call to the thread of the control. The delegate can be an instance of EventHandler. In this case, the sender parameter will contain this control, and the event parameter will contain EventArgs.empty. The delegate can also be a MethodInvoker instance or a list of void parameters Other delegates. Calling EventHandler or MethodInvoker is faster than calling other types of entrustments. "
Ok, I have finished INVOKE, the way, BeginInvoke, there is no doubt that this is the asynchronous version of Invoke (INVOKE is completed synchronous), but you don't want to confuse the BeginInvoke from the SYSTEM.WINDOWS.FORMS.METHODInvoker, both They are all use of different threads to complete the work, but the control's BeginInvoke method always uses the UI thread, while other asynchronous commissioning methods are the threads in the thread pool. In terms of Invoke, use BeGinInvoke a little more troubles, but it is still the same, asynchronous is better than synchronization, despite complex. For example, the synchronization method may have a deadlock: Worker threads will block when INVOKE synchronously calls the UI thread, and if the UI thread is waiting for the worker thread what to do when doing something? Therefore, it is possible to use asynchronous methods when using asynchronous methods.
Below we use the knowledge you have learned to rewrite the simple example above:
// This is the label control private label lblstatus defined by the UI thread; .... // The following method does not execute the private void RunsonWorkerthread () {dosomething on ui thread object [] PLIST [] PLIST [] PLIST [] PLIST [] PLIST [] PLIST [] = {this, system.eventargs.empty}; lblstatus.beginInvoke (new system.eventhandler (updateui), plist);} ....
/ / Switch back to the UI thread execution of the entry private void updateui (Object O, System.EventArgs e) {// Now no problem, using invoke makes the thread always returns to the UI thread, so we can rest assured that the members of the control LBLSTATUS.TEXT = "finished!";
Fifth, regarding multi-threaded programming also considers synchronization problems between threads, deadlock and contention, there are many articles related to such problems, we will not have explained.