[C # Learning] How to invoke WinForm in multiple threads

Source: Internet
Author: User
Tags bool thread

The problem arises:

My WinForm program has a worker thread that updates the main window, but the document prompts me not to call this form in multiple threads (why?). , and the fact that my program often collapses when I call. How do I call a method in form from multiple threads?

Answer:

Each WinForm class (including the control class) derived from the control class relies on the underlying Windows message and a message pump loop (Messages pump loop). The message loop must have a corresponding thread, because the message sent to a window is actually sent only to the thread that created the window. The result is that even if you provide synchronization (synchronization), you cannot invoke these processing messages from multiple threads. Most plumbing are hidden because WinForm is binding the message to the event-handling method with a proxy (delegate). WinForm transforms Windows messages into an agent-based event, but you must be aware that only the thread that created the form can call its event-handling method because of the original message loop. If you call these methods in your own thread, they will handle the event in that thread instead of processing it in the specified thread. You can invoke any method that is not part of the message processing from any thread.

The control class (and its derived classes) implements an interface, ISynchronizeInvoke, defined under the System.ComponentModel namespace, to handle the problem of calling the message processing method in multiple threads:

public interface ISynchronizeInvoke
{
 object Invoke(Delegate method,object[] args);
 IAsyncResult BeginInvoke(Delegate method,object[] args);
 object EndInvoke(IAsyncResult result);
 bool InvokeRequired {get;}
}

ISynchronizeInvoke provides a common standard mechanism for making method calls in objects in other threads. For example, if an object implements ISynchronizeInvoke, then the client on the thread T1 can invoke the ISynchronizeInvoke invoke () method in that object. The implementation of the Invoke () method blocks (block) the invocation of the thread, sends the call to the T2, marshal it, executes the call in T2, sends the return value T1, and then returns to the T1 client. The Invoke () method locates the invocation of the method in T2 with an agent and takes an ordinary object array as its argument.

The caller can also check the InvokeRequired property because you can either call ISynchronizeInvoke in the same thread or reposition it (redirect) to another thread. If the return value of InvokeRequired is false, the caller can call the object's method directly.

For example, suppose you want to call the Close method in a form from another thread, you can use a predefined MethodInvoker proxy and invoke the Invoke method:

Form form;
/* obtain a reference to the form,
then: */
ISynchronizeInvoke synchronizer;
synchronizer = form;
if(synchronizer.InvokeRequired)
{
MethodInvoker invoker = new
MethodInvoker(form.Close);
synchronizer.Invoke(invoker,null);
}
else
form.Close();

ISynchronizeInvoke is not only used in WinForm. For example, a calculator class provides an Add () method that adds two numbers, which are implemented through ISynchronizeInvoke. The user must determine that the call to the Isynchronizeinvoke.invoke () method is executed on the correct thread.

C # writes calls in the correct thread

List A. The Add () method of the Calculator class is used to add two digits. If the user calls the Add () method directly, it executes the call in the user's thread, and the user can write the call to the correct thread through Isynchronizeinvoke.invoke ().

List A:

public class Calculator:isynchronizeinvoke
{
public int Add (int arg1,int arg2)
{
int threadID = Thread.CurrentThread.GetHashCode ();
Trace.WriteLine ("Calculator thread ID is" + threadid.tostring ());
return arg1 + arg2;
}
ISynchronizeInvoke implementation
public Object Invoke (Delegate method,object[] args)
{
Public IAsyncResult BeginInvoke (Delegate method,object[] args)
{
public Object EndInvoke (IAsyncResult result)
{
public bool InvokeRequired
{
}
}
Client-side Code
public delegate int adddelegate (int arg1,int arg2);
int threadID = Thread.CurrentThread.GetHashCode ();
Trace.WriteLine ("Client thread ID is" + threadid.tostring ());
Calculator Calc;
/* Some code to initialize Calc */
AddDelegate adddelegate = new AddDelegate (Calc. ADD);
object[] arr = new object[2];
Arr[0] = 3;
ARR[1] = 4;
int sum = 0;
sum = (int) Calc. Invoke (Adddelegate,arr);
Debug.Assert (sum ==7);
/* Possible output:
Calculator thread ID is 29
Client thread ID is 30
*/

You may not want to make a synchronous call because it is packaged and sent to another thread. You can implement it through the BeginInvoke () and EndInvoke () methods. You can follow the general. NET Asynchronous Programming mode (Asynchronous programming model) to use these methods: Send the call with BeginInvoke (), use EndInvoke () to implement the wait, or to prompt at completion and collect return results.

It is also worth mentioning that the ISynchronizeInvoke method is not a security type. A type mismatch can result in an exception being thrown at execution time, not a compilation error. So be careful when using isynchronizeinvoke because the editor cannot check out execution errors.

Implementing ISynchronizeInvoke requires that you use an agent to dynamically invoke methods in late-bound (late binding). Each type of proxy provides DynamicInvoke () method: public Object DynamicInvoke (object[)

args);

Theoretically, you have to put a method agent in a real thread that needs to provide the object to run, and call the DynamicInvoke () method in the proxy in the Invoke () and BeginInvoke () methods. The implementation of ISynchronizeInvoke is an unusual programming skill, and the source file included in this article contains a helper class called Synchronizer and a test program, This test program is used to demonstrate how the Calculator class in List A uses the Synchronizer class to implement ISynchronizeInvoke. Synchronizer is a common implementation of ISynchronizeInvoke, you can use its derived classes or use it as an object, and assign the ISynchronizeInvoke implementation to it.

An important element used to implement Synchronizer is the use of a nested class (nested Class) called Workerthread. There is a work item (work item) query in Workerthread. The WorkItem class contains method proxies and parameters. Invoke () and BeginInvoke () are used to add a work item instance to the query. Workerthread creates a new. NET worker thread, which is responsible for monitoring the query tasks for work items. After you have queried the project, the worker reads them and then calls the DynamicInvoke () method.

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.