Threading & Cross Threading in C#.NET, How do I change ComboBox Data from another Thread?
I need to use threading in my app, but I don't know how to perform a cross threading operation.
I want to be able to change the text of a form object (in this case a Combo Box), from another thread, I get the error:
Cross-thread operation not valid: Control 'titlescomboBox' accessed from a thread other than the thread it was created on.
I don't really understand how to use the invoke and begin invoke functions, So im really looking for a dead simple example and explanation for this so I can learn around that.
Also any beginner tutorials would be great, I found a few, but their all so different, I don't understand exactly what I need to do to perform cross threading ops.
Here is the code:
// Main Thread. On click of the refresh button
private void refreshButton_Click(object sender, EventArgs e)
{
titlescomboBox.Items.Clear();
Thread t1 = new Thread(updateCombo);
t1.Start();
}
// This function updates the combo box with the rssData
private void updateCombo()
{
rssData = getRssData(channelTextBox.Text); // Getting the Data
for (int i = 0; i < rssData.GetLength(0); i++) // Output it
{
if (rssData[i, 0] != null)
{
// Cross-thread operation not valid: Control 'titlescomboBox'
// accessed from a thread other than the thread it was created on.
titlescomboBox.Items.Add(rssData[i开发者_如何转开发, 0]); // Here I get an Error
}
titlescomboBox.SelectedIndex = 0;
}
}
I use the following helper class:
public static class ControlExtensions
{
public static void Invoke(this Control control, Action action)
{
if (control.InvokeRequired)
{
control.Invoke(new MethodInvoker(action), null);
}
else
{
action.Invoke();
}
}
}
Now you can call something like MyCombo.Invoke(() => { MyCombo.Items.Add(something); })
--- or any other control (such as the form) before the invoke since they are all created on the main thread.
The thing is that controls can only be accessed from the thread they were created on (the main application thread in this case).
HTH
This exception is thrown because of you are trying to access to a control members that is created on another thread. When using controls you should access the control members only from the thread that the control created on.
The control class helps you to know weather the control is no on the thread that is created on or not by providing InvokeRequeired
property. so if 'control.InvokeRequeired' returns true that indicates that you are on a different thread. to help you out. Control support Invoke
and BeginInvoke
methods that will handle the execution of method to the control main thread. So:
If you are using 3.5 and above, I suggest you to use the extension method that Eben Roux
show in his answer.
For 2.0:
// This function updates the combo box with the rssData
private void updateCombo()
{
MethodInvoker method = new MethodInvoker(delegate()
{
rssData = getRssData(channelTextBox.Text); // Getting the Data
for (int i = 0; i < rssData.GetLength(0); i++) // Output it
{
if (rssData[i, 0] != null)
{
// Cross-thread operation not valid: Control 'titlescomboBox'
// accessed from a thread other than the thread it was created on.
titlescomboBox.Items.Add(rssData[i, 0]); // Here I get an Error
}
titlescomboBox.SelectedIndex = 0;
}
});
if (titlescomboBox.InvokeRequired)//if true then we are not on the control thread
{
titlescomboBox.Invoke(method);//use invoke to handle execution of this delegate in main thread
}
else
{
method();//execute the operation directly because we are on the control thread.
}
}
if you use C# 2.0 this
Take a look at this What is the best way to update form controls from a worker thread? - it should resolve your issue.
精彩评论