When developing a window application, you often need to display the steps on the interface. For a simple example, create a winform program, access a button and a label on the form. When you click the button, perform 100 cycles. The number of current cycles is displayed in real time on the label. A simple method is to use application. doevents. The Code is as follows:
private void btnTest_Click(object sender, EventArgs e){ for (int i = 0; i < 100; i++) { Thread.Sleep(100); label1.Text = i + "/100"; Application.DoEvents(); }}
If the above Code removes application. doevents (); When a button is clicked, the program gets stuck until the loop is executed completely. When the loop is large enough, it cannot be tolerated. However, it is okay to use application. doevents () for a small amount of data. If you use application. doevents () for a large amount of data, performance issues may occur. Therefore, application. doevents () should be used with caution. multithreading can be used to solve the problem of large data volumes. As follows:
private void btnTest_Click(object sender, EventArgs e){ Thread thread = new Thread(new ThreadStart(DoWork)); thread.Start();}private void DoWork(){ for (int i = 0; i < 100; i++) { Thread.Sleep(100); label1.Text = i + "/100"; }}
Hmm? If an exception occurs, right? After the above Code is run, "Inter-thread operations are invalid: Never access it by creating a thread that does not create the control" label1 ." . For more information about the cause, Google. However, the above Code seems to work normally in vs03. Change the code to the following to run properly:
private void btnTest_Click(object sender, EventArgs e){ Thread thread = new Thread(new ThreadStart(DoWork)); thread.Start();}private void DoWork(){ for (int i = 0; i < 100; i++) { Thread.Sleep(100); this.Invoke(new Action<string>(this.ChangeLabel),i.ToString()); }}private void ChangeLabel(string i){ label1.Text = i + "/100";}
If it takes too much trouble to write a changelabel method, you can write it as an anonymous method, as shown below:
private void btnTest_Click(object sender, EventArgs e){ Thread thread = new Thread(new ThreadStart(DoWork)); thread.Start();}private void DoWork(){ for (int i = 0; i < 100; i++) { Thread.Sleep(100); this.Invoke(new Action(delegate(){label1.Text=i+"/100";})); }}
You can also remove the dowork method using the anonymous method:
private void btnTest_Click(object sender, EventArgs e){ Thread thread = new Thread(new ThreadStart(delegate() { for (int i = 0; i < 100; i++) { Thread.Sleep(100); this.Invoke(new Action(delegate() { label1.Text = i + "/100"; })); } })); thread.Start();}
If you want to pass parameters to the dowork method, you cannot use the threadstart class. You should use the parameterizedthreadstart class, as shown below:
private void btnTest_Click(object sender, EventArgs e){ string name = "oec2003"; Thread thread = new Thread(new ParameterizedThreadStart(DoWork)); thread.Start(name);}private void DoWork(object name){ for (int i = 0; i < 100; i++) { Thread.Sleep(100); this.Invoke(new Action(delegate(){label1.Text=name+":"+ i+"/100";})); }}
We can also use thread pools for implementation.
private void btnTest_Click(object sender, EventArgs e){ ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));}private void DoWork(object o){ for (int i = 0; i < 100; i++) { Thread.Sleep(100); this.Invoke(new Action(delegate(){label1.Text=i+"/100";})); }}
Use the anonymous method:
private void btnTest_Click(object sender, EventArgs e){ ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object o) { for (int i = 0; i < 100; i++) { Thread.Sleep(100); this.Invoke(new Action(delegate() { label1.Text = i + "/100"; })); } }));}
At ordinary times, there are few Windows applications, and they do not have a very deep understanding of multithreading. Let us know what's wrong.
Return to the beginning (INDEX)