Objective
In the rich client app, if you run some long tasks in the main thread, your application's UI will not work properly. Because the main thread is responsible for the message loop, the corresponding mouse and other events also show the UI.
So we can start a thread to handle the task for a long time, but only the main thread in the rich client can update the UI's controls.
Workaround
To put it simply, we need to update the UI thread's controls from other threads, and we need to hand this action to the UI thread (thread marshal).
Method 1:
In the underlying operation, the following methods can be used:
- In WPF, call the BeginInvoke or Invoke method in the dispatcher class of element
- Metro, call the Runasync or Invoke method in the Dispatcher class
- WinForm, call the BeginInvoke or Invoke method directly in the control
All of the above method parameters are a delegate, using this delegate to represent the tasks that need to be handled:
Public IAsyncResult BeginInvoke (Delegate method);
The Begininvoke/runasync method is to push this delegate to the message queue of the UI thread, which is the queue of the previously mentioned mouse, keyboard events, and so on.
The Invoke method also pushes delegate to the message queue, but it also blocks until this delegate is processed by the UI thread. So generally speaking, we still use the Begininvoke/runasync method.
For the app, we can think of it as pseudo-code:
while (! for on is it? Keyboard Event delegateDelegate & Post result}
Then we'll use WinForm to Demo:
Public Partial classform1:form{ PublicForm1 () {InitializeComponent (); NewThread (work). Start (); } voidWork () {Thread.Sleep ( the); Updatemessage ("July Luo Thread Test"); } voidUpdatemessage (stringmessage) {Action Action= () = Lbljulyluo.text =message; This. BeginInvoke (action); }}
Method 2
In the System.ComponentModel namespace, there are SynchronizationContext abstract classes, which can also handle thread marshal.
In Wpf,metro, the subclasses of this class are defined in WinForm, and can be obtained with synchronizationcontext.current and then called the Post method, which can be understood to post the tasks of other threads to the UI thread.
For demo:
Public Partial classform1:form{SynchronizationContext _uisynccontext; PublicForm1 () {InitializeComponent (); _uisynccontext=synchronizationcontext.current; } voidWork () {Thread.Sleep ( the); Updatemessage ("July Luo Thread Test"); } voidUpdatemessage (stringmessage) {_uisynccontext.post (_= = Lbljulyluo.text = message,NULL); }}
The SynchronizationContext class also has a send method that is consistent with the Invoke method we mentioned above.
Of course, there's the BackgroundWorker class, which uses SynchronizationContext internally, so it can also update the UI thread in other threads.
Summarize
The UI thread in the rich client always handles the message loop, regardless of whether it is pushed into the message queue for the UI thread to process.
Rich client WPF, Winform multithreaded update UI control