Reprint: http://www.cnblogs.com/nsky/p/4436309.html
The control cannot be accessed across threads after the. Net2. , the controls on the form are created by the current thread when the user executes a method asynchronously: Assign a value to a control on a form in that method, and remember that when an asynchronous delegate is executed, it actually
is to open a thread to execute that method, which will cause an error: the operation between threads is invalid: it is accessed from a thread that does not create the control "XXX".
In C # WinForm development, this is a more common exception: the Inter-threading operation is not valid, and it is accessed from a thread that does not create the control "XXX". This anomaly comes from. A limitation of NET2: A worker thread cannot access a control created by a window thread. There are two main workarounds, one of which is to set Checkforillegalcrossthreadcalls = False in the window thread, and the other to be cumbersome, invoking the Invoke method in the same way as a delegate.
Public Form1 () { InitializeComponent (); Control.checkforillegalcrossthreadcalls = false; }
But the above is not the recommended method. A better way is to use a delegate to solve
private void Button1_Click (object sender, EventArgs e) { new Action (show). BeginInvoke (null, NULL); } void Show () { //async method outside. This form does not feign animation while (true) { thread.sleep (a); Action AC = new action (showtext); This. Invoke (AC); Implement update data on form in synchronous Method}}///<summary>//Update data/// </summary> void Showtext () { richtextbox1.appendtext ("Update \ n"); }
Or use the InvokeRequired property to determine
/*
Summary:
Gets a value that indicates whether the caller must call the Invoke method when making a method call to the control, because the call is in a thread other than the one on which the control is created.
//
return Result:
If the System.Windows.Forms.Control.Handle of the control is created on a different thread than the calling thread (the description you must pass the Invoke
method is called for the control), or false.
private void Button1_Click (object sender, EventArgs e) {//new Action (show). BeginInvoke (null, NULL); New Action (SHOW1). BeginInvoke (null, NULL); } void Show1 () {while (true) {Thread.Sleep (2000);//Simulation Wait effect Show2 (); }} void Show2 () {//description of the current external thread/*//Summary://Get a value indicating that the calling Party must call the Invoke method when making a method call to the control, because the call is in a thread other than the thread on which the control is created. Returns the result://If the System.Windows.Forms.Control.Handle of the control is created on a different thread than the calling thread (instructions you must pass the Invoke//party Is true if the control is called), otherwise false. */if (invokerequired) {/* Since it is an external thread, there is no permission to access the control on the main thread * Therefore, to access the main thread, open an asynchronous The method to be executed by the bundle is given to the main thread execution */action AC = new Action (SHOW2); This. Invoke (AC); After execution here. Then the invokerequired is false. Because this is already the main thread accessing the currently created control} else {richtextbox1.appendtext ("update 77\n"); } }
See the first paragraph of the code is not very uncomfortable feeling. The Showtext () method is also independent of an assignment statement. Here you can simplify the code, use anonymous functions, or use a simpler lambda expression (this method does not require other user calls to consider anonymous functions). So look at the simplified code.
private void Button1_Click (object sender, EventArgs e) {new Action (show). BeginInvoke (null, NULL); } void Show () {//Async method outside. This form does not suspend animation while (true) {Thread.Sleep (2000);//Waits outside the Async method so that the form does not feign death//act Ion AC = new Action (showtext); This. Invoke (AC); Implement update data on form in synchronous method//anonymous function action at = new Action (delegate () {richtextbox1.appendtext ("update \ n") ); }); Lambda expression Simpler Action AT1 = new Action (() = {richtextbox1.appendtext ("update \ n");}); This. Invoke (at);
Here this. Executes this method on behalf of a thread on the current form (control)
This is not necessarily the case, as long as the controls on the current form are available, such as
Button1. Invoke (at);
This. Invoke (at);//invoke: Executes the specified delegate on the thread that owns the underlying window handle for this control.
Richtextbox1.invoke (at);
Button1. Invoke (at);
} }
The same code that we used to judge the invokerequired attribute in the same way is shorthand for the lambda expression.
private void Button1_Click (object sender, EventArgs e) { new Action (SHOW1). BeginInvoke (null, NULL); } void Show1 () { //while (true) //{ // Thread.Sleep (2000);//Analog wait effect // show2 (); } for (int i = 0; i < i++) { thread.sleep (2000);//Simulation Wait Effect //show2 (); if (invokerequired) { Action ac = new Action (() = {Richtextbox1.appendtext ("update 767\n");}); This. Invoke (AC); After execution here. Then the invokerequired is false. Because this is already the main thread accessing the currently created control}}}
Invalid inter-thread operation: access it from a thread that is not creating the control "Button1".