建议使我的线程池设置安全,DRY和可扩展

本文关键字:安全 DRY 可扩展 设置 我的 线程 | 更新日期: 2023-09-27 18:13:50

现在我正在生成3个线程来做一些并发工作,我使用线程池来设置它,因为我希望所有线程并发运行,但在继续之前完成所有线程。下面是代码的要点:

_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个方法,只是为了set()正确的线程。

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();
}

显然它不是很干,因为我想有4个或5个线程,但要确保Set()是设置正确的_resetEvent当它完成。

关于我如何安全地做到这一点并使其更DRY和可扩展的任何建议?

建议使我的线程池设置安全,DRY和可扩展

您可以使用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。对于/ForEach,使用:

int numToRun = 42;
ParallelEnumerable.Range(0, numToRun).ForAll(i => (new WorkerClass()).Process());

类似于Parallel。每一个可能更好。

否则,只需将传入参数视为数组中的索引即可:

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