简体   繁体   English

具有BindingList的多线程C#应用程序 <T> 和DataGridView

[英]Multi-thread C# application with BindingList<T> and DataGridView

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 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. 我有一个Timer线程,用于更新列表的一部分(例如Device.status字段)和UI线程,其中这些列表绑定到DataGridView表,并且某些字段(例如Device.description字段)可以在此处手动编辑。

My problem is that when Timer thread wants to update Binding list content then I get InvalidOperationException : 我的问题是,当Timer线程想要更​​新绑定列表内容时,我会收到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. 我在修改MyGlogals列表的每个代码块周围使用lock(listLock)语句,但无法控制DataGridView如何处理列表。 How to make this application thread safe? 如何使该应用程序线程安全?

you cannot update the UI thread from a different thread. 您不能从其他线程更新UI线程。

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: 并在bg_DoWork中:

  void bg_DoWork(object sender, DoWorkEventArgs e)
  {
     foreach (Device device in MyGlobals.devicesList)
     {
           device.text = "newText";
     }
  }

The GUI itself needs to be updated from the GUI thread (main thread). GUI本身需要从GUI线程(主线程)进行更新。 .NET provides the BackgroundWorker class for just this purpose. .NET为此提供了BackgroundWorker类。 Comms with the GUI can be done via either/or ProgressChanged and RunWorkerCompleted events, in which you can pass an object of choice (eg to be displayed). 可以通过/或ProgressChangedRunWorkerCompleted事件完成与GUI的通信,您可以在其中传递选择的对象(例如,要显示的对象)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM