private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(1000); // do something
this.textBox1.Text += @"
line " + Convert.ToString(i);
}
}
The code above will update the text box, but only after the whole loop, i.e 5 seconds. That was because this is a single thread application. The update to the text box will be executed after the click event.
If you want real time update, you will need to create a thread.
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(DoSomeWork);
thread.Start();
}
private void DoSomeWork()
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(1000); // do something
this.textBox1.Text += @"
line " + Convert.ToString(i);
}
}
But when you run the code above, you will get "Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on." exception
That was because the text box was created by the main thread. You can not access it directly from a new thread. There are a lot of articles talking about this issue. You may check this one. Basically what they are saying is you need a way to call back from the new thread. Here is quote talking about the Control.InvokeRequired property from MSDN:
Controls in Windows Forms are bound to a specific thread and are not thread safe. Therefore, if you are calling a control's method from a different thread, you must use one of the control's invoke methods to marshal the call to the proper thread. This property can be used to determine if you must call an invoke method, which can be useful if you do not know what thread owns a control.
Below is the sample code. When you run it, you will see that the text box will be updated every second.
public partial class Form1 : Form
{
private delegate void UICallerDelegate(int i);
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Thread thread = new Thread(DoSomeWork);
thread.Start();
}
private void DoSomeWork()
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(1000); // do something
UpdateTextbox(i);
}
}
private void UpdateTextbox(int i)
{
if (this.InvokeRequired)
{
UICallerDelegate dlg = new UICallerDelegate(UpdateTextbox);
BeginInvoke(dlg, i);
}
else
{
this.textBox1.Text += @"
" + Convert.ToString(i);
}
}
}
No comments:
Post a Comment