c# - 使我的线程池设置安全、干燥和可扩展的建议

标签 c# multithreading threadpool

现在我正在生成 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 和可扩展的任何建议?

最佳答案

您可以只使用 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());

关于c# - 使我的线程池设置安全、干燥和可扩展的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16570885/

相关文章:

c# - 谁负责检查空引用异常?

c# - 关闭或不关闭数据库中的连接

c++ - 在函数静态变量上调用 setter 一次

java - 如何通过传递新线程作为参数来执行执行器服务?

c# - 表达总是真实的,即使它不是

c# - Windows 服务 : The underlying provider failed on Open 上的间歇性错误

multithreading - 无法将 std::vector<std::unique_ptr<>> 传递给 std::thread

java - Java多线程奇怪的问题。某些线程自行关闭?

java - 如何有效地重置线程池

tomcat - 一个Tomcat线程占用多少内存?