2

public static class MyGlobalsアプリケーション全体の変数と、これらの変数を処理および変更する複数のスレッドがあります。

public static class MyGlobals
{
    public static BindingList<Device> devicesList;
    public static BindingList<Device> availableList;
    public static object listLock = new object();
}

Timerリストの一部 (フィールドなど) を更新する1 つのスレッドとDevice.status、これらのリストがDataGridViewテーブルにバインドされ、フィールドの一部 (Device.descriptionフィールドなど) を手動で編集できる UI スレッドがあります。

私の問題は、Timer スレッドが Binding リストのコンテンツを更新しようとすると、次のようになることですInvalidOperationException

Additional information: Cross-thread operation not valid: Control 'gridView1' accessed from a thread other than the thread it was created on.

lock(listLock)リストを変更するすべてのコード ブロックでステートメントを使用していますが、リストの処理MyGlogals方法を制御できませんDataGridView。このアプリケーションをスレッドセーフにする方法は?

4

2 に答える 2

1

GUI 自体は、GUI スレッド (メイン スレッド) から更新する必要があります。.NET は、まさにこの目的のためにBackgroundWorkerクラスを提供します。GUI との通信は、ProgressChangedおよびRunWorkerCompletedイベントのいずれかまたは両方を介して行うことができます。このイベントでは、選択したオブジェクト (表示されるものなど) を渡すことができます。

于 2013-09-12T08:42:15.397 に答える
1

別のスレッドから UI スレッドを更新することはできません。

この投稿を使用して解決できます。たとえば、

     foreach (Device device in MyGlobals.devicesList)
     {
        Invoke(new MethodInvoker(delegate {
             device.text = "newText";
        }));
     }

またはバックグラウンド ワーカーを使用します。

     BackgroundWorker bg = new BackgroundWorker();
     bg.DoWork += new DoWorkEventHandler(bg_DoWork);
     bg.RunWorkerAsync();

そしてbg_DoWorkで:

  void bg_DoWork(object sender, DoWorkEventArgs e)
  {
     foreach (Device device in MyGlobals.devicesList)
     {
           device.text = "newText";
     }
  }
于 2013-09-12T08:38:54.243 に答える