1

現在、いくつかの同時作業を行うために 3 つのスレッドを生成しています。すべてのスレッドを同時に実行したいが、続行する前にすべてのスレッドを完了させたいので、Threadpooling を使用してセットアップしました。コードの要点は次のとおりです。

_resetEvents = new ManualResetEvent[3];

_resetEvents[0] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(DoWorkA);
_resetEvents[1] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(DoWorkB);
_resetEvents[2] = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(DoWorkC);

WaitHandle.WaitAll(_resetEvents);

しかし、私のメソッドはすべて同じコード ベースを使用しています。適切なスレッドを設定するためだけに 3 つのメソッドに分割しました。

private void DoWorkA(object o) {
    var workerClass = new WorkerClass();
        workerClass.Process();
    _resetEvents[0].Set();
}
private void DoWorkB(object o) {
    var workerClass = new WorkerClass();
        workerClass.Process();
    _resetEvents[1].Set();
}
private void DoWorkC(object o) {
    var workerClass = new WorkerClass();
        workerClass.Process();
    _resetEvents[2].Set();
}

明らかに、あまり DRY ではありません。4 つまたは 5 つのスレッドを使用したいのですが、完了時に Set() が正しい _resetEvent を設定していることを確認したいからです。

これを安全に実行し、よりドライでスケーラブルにする方法について何か提案はありますか?

4

2 に答える 2

5

スレッドの代わりに TPL からタスクを使用するだけでよく、待機ハンドルは必要ありません。

Action execute = () => { 
    var worker = new WorkerClass();
    worker.Process();
};

var task1 = Task.Run(execute);
var task2 = Task.Run(execute);
var task3 = Task.Run(execute);
Task.WaitAll(task1, task2, task3);

または、代わりに:

Action execute = () => (new WorkerClass()).Process();

Parallel.Invoke(execute, execute, execute);

これを N 個の項目にスケーリングする必要がある場合は、PLINQ または Parallel.For/ForEach に切り替えて、次を使用できます。

int numToRun = 42;
ParallelEnumerable.Range(0, numToRun).ForAll(i => (new WorkerClass()).Process());
于 2013-05-15T16:58:43.300 に答える
1

Parallel.ForEachのようなものが良いかもしれません。

それ以外の場合は、着信引数を配列内のインデックスとして扱うだけで十分な場合があります。

private void DoWork(object index) 
{
    var workerClass = new WorkerClass();
        workerClass.Process();
    _resetEvents[(int)index].Set();
}

ThreadPool.QueueUserWorkItem(DoWork, 0);
于 2013-05-15T17:01:04.013 に答える