6

に項目を追加する必要があるワーカー スレッドがありますBindingList。ただし、BindingListは にデータバインドされていDataGridViewます。したがって、リストに追加しようとすると、InvalidOperationException (Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on.)

通常、この例外に対して次のようにします。

if(winformControl.InvokeRequired) {
    winformControl.Invoke(MethodDelegate);
}

ただし、Winform コントロールが見えないため、データバインディングは物事を混乱させます。私が持っているのは、例外をスローする次の行だけです。

ClassInstance.MyBindingList.Add(myObject);

このシナリオ専用のソリューションがある場合は、すばらしいことです。

そうでない場合、メインスレッドに特定のメソッドを実行するようにワーカースレッドに指示するにはどうすればよいですか (ワーカースレッドによって提供されるいくつかのパラメーターを使用)。私のワーカー スレッドは現在 (データベースへの書き込みなど) 実際に多くの処理を行っており、すべてがスレッド セーフかどうかはわかりません。私は学生で、マルチスレッドは初めてですが、それはまだ私の得意分野ではありません。

4

4 に答える 4

1

ここでの 1 つのオプションは、このようBindingList<T>に同期コンテキストを使用するように指示することですが、これはおそらく最良の方法ではありません。(リストに直接追加するのではなく)イベントなどを介してデータを公開できるかどうか疑問に思います-その後、適切なスレッドに送信してUIモデルに追加することにより、UIにイベントを処理させます.

于 2010-08-12T21:09:38.720 に答える
1

ワーカー クラス コンストラクターで、これを試してください。

private System.Threading.SynchronizationContext mContext = null;

/// <summary>
/// Constructor for MyBackgroundWorkerClass
/// </summary>
public MyBackgroundWorkerClass(System.Threading.SynchronizationContext context)
{
    mContext = context;
}

次に、UI スレッドで何かを呼び出す必要がある場合:

private void CallOnTheUiThread(object dataToPassToUiThread)
{
    // Make sure the code is run on the provided thread context.
    // Make the calling thread wait for completion by calling Send, not Post.
    mContext.Send(state =>
        {
            // Change your UI here using dataToPassToUiThread.  
            // Since this class is not on a form, you probably would 
            // raise an event with the data.
        }
    ), null);
}

UI スレッドのフォームからワーカー クラスを作成する場合、これを同期コンテキストとして渡します。

private void Form1_Load(object sender, EventArgs e)
{
    var worker = new MyBackgroundWorkerClass(SynchronizationContext.Current);
}
于 2010-08-12T21:20:52.143 に答える
0

メイン、UI、スレッドにイベントを発生させることができ、次のようなものがあります。

if (this.InvokeRequired)
{
    this.Invoke(...);
}

したがって、メインウィンドウ自体でテストしています。

于 2010-08-12T21:05:23.943 に答える
0

要件が与えられれば、BackgroundWorkers は簡単に実装できます。

データベースへの保存など、バックグラウンド スレッドで実行される DoWork メソッドを定義します。DoWork が終了すると、RunWorkerCompleted メソッドが呼び出されます。RunWorkerCompleted は UI スレッドで実行され、ビューのリストを問題なく更新できます。

// on the UI thread
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += DoWork;
worker.RunWorkerCompleted += RunWorkerCompleted;
worker.RunWorkerAsync("argument");

イベント:

static void DoWork(object sender, DoWorkEventArgs e)
{
    e.Result = "4";
}

static void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
        string a = (string)e.Result;
        Console.WriteLine(a);
    }
    else
    {
        Console.WriteLine(e.Error.Message);
    }
}
于 2010-08-12T22:26:53.373 に答える