Reputation: 11971
I am quite new when it comes to threading but I am getting an InvalidOperationException
when using the following code. I understand that it is trying to access importFileGridView
but this was created by the UI thread which creates the exception. My question is, how do I resolve this? Is it possible for GetAllImports to have a return type? How do I access temp
from my UI thread?
ThreadPool.QueueUserWorkItem(new WaitCallback(GetAllImports), null);
private void GetAllImports(object x)
{
DataSet temp = EngineBllUtility.GetAllImportFiles(connectionString);
if (temp != null)
importFileGridView.DataSource = temp.Tables[0];
else
MessageBox.Show("There were no results. Please try a different search", "Unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Upvotes: 5
Views: 1424
Reputation: 7817
What reed said but I like this syntax a bit better:
What happens is you're creating a delegate function which will be passed as a parameter to the UI thread via Control.Invoke
which Invokes it, this way the UI thread makes the changes to the importFileGridView
.
importFileGridView.Invoke((MethodInvoker) delegate {
importFileGridView.DataSource = temp.Tables[0];
});
You could also write this like this:
//create a delegate with the function signature
public delegate void SetDateSourceForGridViewDelegate (GridView gridView, Object dataSource);
//write a function that will change the ui
public void SetDataSourceForGridView(GridView gridView, Object dataSource)
{
gridView.DataSource = dataSource;
}
//Create a variable that will hold the function
SetDateSourceForGridViewDelegate delegateToInvoke = SetDataSourceForGridView;
//tell the ui to invoke the method stored in the value with the given paramters.
importFileGridView.Invoke(delegateToInvoke, importFileGridView, temp.Tables[0]);
and I'd advice the use of MethodInvoker
over Action
see: here
Upvotes: 0
Reputation: 564413
You can't change a user interface component on a background thread. In this case, setting the DataSource must be done on the UI thread.
You can handle this via Control.Invoke
or Control.BeginInvoke
, like so:
private void GetAllImports(object x)
{
DataSet temp = EngineBllUtility.GetAllImportFiles(connectionString);
if (temp != null)
{
// Use Control.Invoke to push this onto the UI thread
importFileGridView.Invoke((Action)
() =>
{
importFileGridView.DataSource = temp.Tables[0];
});
}
else
MessageBox.Show("There were no results. Please try a different search", "Unsuccessful", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Upvotes: 3