Reputation: 529
I have public static class MyGlobals
for my application wide variables and multiple threads processing and changing these variables.
public static class MyGlobals
{
public static BindingList<Device> devicesList;
public static BindingList<Device> availableList;
public static object listLock = new object();
}
I have one Timer
thread, that updates part of the list (for example Device.status
fields) and UI thread where these lists are binded to DataGridView
tables and some of the fields (for example Device.description
field) can be manually edited there.
My problem is that when Timer thread wants to update Binding list content then I get InvalidOperationException
:
Additional information: Cross-thread operation not valid: Control 'gridView1' accessed from a thread other than the thread it was created on.
I use lock(listLock)
statement around every code block where I modify MyGlogals
lists, but I cannot control how DataGridView
handles the lists. How to make this application thread safe?
Upvotes: 2
Views: 2402
Reputation: 11577
you cannot update the UI thread from a different thread.
you can use this post to help you solve it: for example do
foreach (Device device in MyGlobals.devicesList)
{
Invoke(new MethodInvoker(delegate {
device.text = "newText";
}));
}
or use background worker:
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerAsync();
and in bg_DoWork:
void bg_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Device device in MyGlobals.devicesList)
{
device.text = "newText";
}
}
Upvotes: 1
Reputation: 15055
The GUI itself needs to be updated from the GUI thread (main thread). .NET provides the BackgroundWorker class for just this purpose. Comms with the GUI can be done via either/or ProgressChanged and RunWorkerCompleted events, in which you can pass an object of choice (e.g. to be displayed).
Upvotes: 1