Here is a solution using Windows Forms. I tried to stay as close to your code as possible, although Foothill's solution is better in my opinion, and you could use it by changing a single line of code:
Dispatcher.Invoke(() => listBox1.Items.Add(i.ToString()));
Should be changed to:
this.Invoke((MethodInvoker)(() => listBox1.Items.Add(i.ToString())));
Yes, we're using lambda expressions. If you're not familiar with them, you should read up on lambda expressions and Anonymous Methods
here, and
here.
Here's my solution (keeping as close to your code as possible):
private void startbtn_Click(object sender, EventArgs e)
{
String comboBox1Text = "";
this.Invoke((MethodInvoker)(() => comboBox1Text = comboBox1.Text));
new System.Threading.Thread(() =>
{
int i = 0;
while (comboBox1Text.Equals("TRUE"))
{
i = i + 1;
this.Invoke((MethodInvoker)(() =>
{
listBox1.Items.Add(i.ToString());
comboBox1Text = comboBox1.Text;
}));
}
}).Start();
}
private void stopbtn_Click(object sender, EventArgs e)
{
comboBox1.Text = "FALSE";
}
This works - I tested it. Let me explain a little about why it works.
As Griff said above, you can only update user interface (UI) elements from the thread that created them. In Windows forms, all controls "know" which thread created them, and even a Form is a control. You can ask a control if you are accessing it from the thread that created it using control.invokeRequired (returns a bool). If it returns true, then you need to "Invoke" the control, or schedule code to run on the UI thread. You do this by calling control.Invoke(). Take a minute, and read up on what control.invoke does
here.
There are many different ways to use control.invoke(), but the one I used in this example - while maybe not the best (I usually set up a helper function to handle UI updates and pass it code in a lambda expression. It makes your code clearer / more readable), works in this example.
If I missed anything,or you have any questions, please feel free to ask.
- Pete