Cross thread access of winform

Problem description

In winform development, we can't avoid using multi-threaded or asynchronous methods in data exchange, so we can't avoid cross thread operations (assignment, property modification) on the control.

Here is a test to illustrate the problem

Click a button to assign textbox asynchronously

Run test results

1 private void button1_Click(object sender, EventArgs e)
2 {        
3               Action<string> action = new Action<string>((str) =>
4               {
5                   // Solve cross thread assignment
6                   this.textBox1.Text = str;              
7               });
8               action.BeginInvoke("Test", null, null);      
9 }

Causes of errors: textBox1 is created by the main thread, asynchronous method (or sub thread) is another thread created, and managed code is executed on. NET. C ා forces that these codes must be thread safe, that is, cross thread access to Windows form controls is not allowed.

Solution

1. In the loading event of the form, set the checkforillegalsthreadcalls property of the C ා built-in control class to false to block the check of cross thread calls by the C ා compiler.

1 //Cancel cross thread access
2 Control.CheckForIllegalCrossThreadCalls = false;

Although using the above methods can ensure the normal operation of the program and realize the application functions, in the actual software development, it is not safe (not in accordance with the. NET security specifications) to do so. In the development of product software, this kind of situation is not allowed. If you want to successfully access the space created by another thread from one thread under the premise of complying with the. NET security standard, you need to use the method callback mechanism of C ා.

2. Use callback function (Application of delegation)

(1) define declaration callback

(2) initialization callback

(3) trigger action

 1         /// <summary>
 2         /// Define delegate
 3         /// </summary>
 4         /// <param name="str"></param>
 5         private delegate void SetValueDelegate(string str);
 6 
 7         /// <summary>
 8         /// Declaration delegation
 9         /// </summary>
10         SetValueDelegate test;
11 
12         /// <summary>
13         /// Callback method
14         /// </summary>
15         /// <param name="str"></param>
16         private void SetTbValue(string str)
17         {
18             this.textBox1.Text = str;
19         }
20 
21         private void button1_Click(object sender, EventArgs e)
22         {
23             // Instantiation delegation    
24             test = new SetValueDelegate(SetTbValue);
25 
26             Action<string> action = new Action<string>((str) =>
27             {
28                   // Solve cross thread assignment                 
29                   this.textBox1.Invoke(test, str);
30              });
31 
32             action.BeginInvoke("Test", null, null);
33         }

I prefer to use event resolution (the principle is the same as delegation), but I save a lot of code

 1         private void button1_Click(object sender, EventArgs e)
 2         {
 3             Action<string> action = new Action<string>((str) =>
 4               {
 5                   // Solve cross thread assignment            
 6                   this.textBox1.Invoke(
 7                       new Action<string>((param) =>
 8                       {
 9                           this.textBox1.Text = param;
10                       }
11                       ), str);
12               });
13 
14             action.BeginInvoke("Test", null, null);
15         }

Tags: C# Windows

Posted on Mon, 02 Dec 2019 05:30:22 -0500 by ilangovanbe2005