C# updates the controls on the UI interface in the worker thread

In C# application development, we often separate the UI thread from the worker thread to prevent the interface from stopping responding. At the same time, we need to update the controls on the UI interface in the working thread.
The following introduces several commonly used methods.
The operation between threads is invalid.
There is a button and a label on the interface. Clicking the button will start a thread to update the value of the Label.

  1. private void button1_Click(object sender, EventArgs e)
  2.         {
  3.             Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel));
  4.             thread1.Start("Update Label");
  5.         }
  6.         private void UpdateLabel(object str)
  7.         {
  8.             this.label1.Text = str.ToString();
  9.         }
copy code

After running, the program will report an error "The cross-thread operation is invalid, accessing it from the thread that did not create "label1""


This is because .NET prohibits calling controls across threads, otherwise anyone can operate the controls, which may cause errors in the end.   

The following introduces several methods of calling controls across threads.

The first method: prohibit the compiler from checking cross-thread access. This is the simplest method, which is equivalent to not checking conflicts between threads and allowing each thread to mess around. Finally, Label1 It is unpredictable what the value of the control is ( this method is not recommended )

  1. public Form1()
  2.         {
  3.             InitializeComponent();
  4.             // add this line
  5.             Control.CheckForIllegalCrossThreadCalls = false;
  6.         }
copy code


The second method: use delegate and invoke to call the control from other threads to call the invoke method of the control, and then you can control the control, for example

  1. private void button2_Click(object sender, EventArgs e)
  2.         {
  3.             Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel2));
  4.             thread1.Start("Update Label");
  5.         }
  6.         private void UpdateLabel2(object str)
  7.         {
  8.             if (label2.InvokeRequired)
  9.             {
  10.                 // When the InvokeRequired property value of a control is true, it means that a thread other than creating it wants to access it
  11.                 Action<string> actionDelegate = (x) => { this.label2.Text = x.ToString(); };
  12.                 // or
  13.                 // Action<string> actionDelegate = delegate(string txt) { this.label2.Text = txt; };
  14.                 this.label2.Invoke(actionDelegate, str);
  15.             }
  16.             else
  17.             {
  18.                 this.label2.Text = str.ToString();
  19.             }
  20.         }
copy code


The third method: use delegate and BeginInvoke to control the control from other threads. Just change the Invoke in the above this.label2.Invoke(actionDelegate, str); to the BeginInvoke method.
The difference between the Invoke method and the BeginInvoke method is that
Invoke The method is synchronous, it will wait for the worker thread to complete,
the BeginInvoke method is asynchronous, it will start another thread to complete the worker thread

The fourth method: Use the BackgroundWorker component (recommended to use this method) BackgroundWorker is used to execute in .NET Controls for multithreaded tasks, which allow programmers to perform some operations on a separate thread. Time-consuming operations such as downloads and database transactions. easy to use
 

  1. private void button4_Click(object sender, EventArgs e)
  2.         {
  3.             using (BackgroundWorker bw = new BackgroundWorker())
  4.             {
  5.                 bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
  6.                 bw.DoWork += new DoWorkEventHandler(bw_DoWork);
  7.                 bw.RunWorkerAsync("Tank");
  8.             }         
  9.         }
  10.         void bw_DoWork(object sender, DoWorkEventArgs e)
  11.         {      
  12.             // This is a background thread, done on another thread
  13.             // here is the worker thread that actually does the work
  14.             // You can do some time-consuming and complicated operations here
  15.             Thread.Sleep(5000);
  16.             e.Result = e.Argument + "Worker thread completed";
  17.         }
  18.         void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  19.         {
  20.             // At this time, the background thread has been completed and returned to the main thread, so the UI control can be used directly
  21.             this.label4.Text = e.Result.ToString();
  22.         }

 

Guess you like

Origin blog.csdn.net/u014090257/article/details/125651551
Recommended