The generation of the problem:
There is a WORKER THREAD in my winform program, but I can't call this form in the document, but in fact I often collapse when calling when calling during calling. Drop. How to call the method from the form from multithreading?
answer:
Each WinForm class (including Control classes) derived from the Control class is performed on the underlying Windows message and a message pump loop. Message loops must have a corresponding thread because messages sent to a Window are actually sent to creating the Window thread. As a result, even if synchronization is provided, you cannot call these processing messages from multi-threads. Most plumbing is hidden because WinForm is binding messages to the event processing method with a proxy. WinForm converts Windows messages into an agent-based event, but you must also pay attention to the initial message loop, only the thread that creates the Form can call its event processing method. If you call these methods in your own thread, they handle events in the thread instead of processing in the specified thread. You can call any ways that do not belong to messages from any thread.
The Control class (and its assignment) implements an interface defined under the System.comPonentModel namespace - ISYNCHRONIZEINVOKE, and handles the problem of calling message processing methods in multi-thread:
public interface ISynchronizeInvoke {object Invoke (Delegate method, object [] args); IAsyncResult BeginInvoke (Delegate method, object [] args); object EndInvoke (IAsyncResult result); bool InvokeRequired {get;}}
IsynchronizeInvoke provides an ordinary standard mechanism for method calls in other threads. For example, if an object is ISYNCHRONIZEINVOKE, the client on the thread T1 can call the ISYNCHRONIZEINVOKE INVOKE () method in this object. Implementation of the INVOKE () method blocks the call of the thread, which will call the package transmission (Marshal) to T2, and perform call in T2, and then send the return value to T1, and then return to the client of T1. The invoke () method is positioned in T2 in a proxy and as its parameters in an ordinary object array.
The caller can also check the InvokeRequired property, because you can call ISYNCHRONIZEINVOKE in the same thread or you can reposition it to other threads. If the return value of InvokeRequired is false, the caller can directly call the method of the object.
For example, suppose you want to call a Close method in a form from another thread, then you can use a pre-defined MethodInvoker agent, and call 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); } elseform.close (); IsynchronizeInvoke is not only used in WinForm. For example, a Calculator class provides an add () method plus two numbers, which is implemented by IsynchronizeInvoke. The user must determine that the call to the isynchronizeInvoke.invoke () method is performed in the correct thread.
C # written in the correct thread
List A. The add () method for the Calculator class is used to add two numbers. If the user calls the add () method directly, it performs calls in the user's thread, and the user can write the correct thread by 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 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 * /
Maybe you don't want to call synchronous calls because it is sent to another thread. You can implement it through the beginInvoke () and endInvoke () methods. You can use these methods in accordance with General .NET Non-Synchronous Mode: Use BeGinInvoke () to send calls, use endInvoke () to implement or use to prompt when completed and collect the return result. It is also worth mentioning that isynchronizeInvoke method is not a safe type. The type does not match will result in an exception when executed, not compiling errors. So you should pay more attention when using IsynchronizeInvoke, because the editor cannot check the execution error. Implementation IsynchronizeInvoke requires you to use a proxy to dynamically modify the method in later binding. Each agent type provides DynamicInvoke () method: public object DynamicInvoke (Object [] args); theoretically, you must put a method agent in a real thread that needs to provide objects and makes invoke ) The DynamicInvoke () method is called from the agent in the beginInvoke () method. ISYNCHRONIZEINVOKE is a non-general programming skill. The source file included in this article contains a Helper Class and a Test Program for the Synchronizer, which is used to demonstrate the Calculator class in the list A. How to use the Synchronizer class to implement IsynchronizeInvoke. Synchronizer is an ordinary implementation of IsynchronizeInvoke, you can use its derive class or use it as an object, and assign IsynchronizeInvoke implementation to it. An important element used to implement SYNCHRONIZER is the use of a nested class called Workerthread. There is a work item in Workerthread. The method proxy and parameters are included in the WorkItem class. Invoke () and beginInvoke () are used to join a work item instance to the query. Workerthread has created a new .NET WORKER thread that is responsible for monitoring the query task of work items. After querying the project, Worker reads them and then calls the DynamicInvoke () method. http://weblogs.asp.net/justin_rogers/articles/126345.aspx