【发布时间】:2018-04-16 02:52:39
【问题描述】:
我正在实现一个具有并发上限的工作引擎。我正在使用信号量等待并发量降至最大值以下,然后使用Task.Factory.StartNew 将异步处理程序包装在try/catch 中,并使用finally 释放信号量。
我意识到这会在线程池上创建线程 - 但我的问题是,当这些任务运行线程之一实际等待时(在真正的 IO 调用或等待句柄上),线程是否返回到池中,就像我一样希望是吗?
如果有更好的方法来实现具有有限并发的任务调度程序,其中工作处理程序是异步方法(返回 Task),我也很想听听。或者,假设理想情况下,如果有一种方法可以让异步方法排队(同样,它是一个 Task-returning 异步方法),感觉不如将它包装在同步委托中并将其传递给 Task.Factory.StartNew,那将看起来很完美..?
(这也让我认为这里有两种并行性:总共处理了多少个任务,以及同时在不同线程上运行了多少个延续。为两者提供可配置选项可能很酷,但不是一个固定的要求..)
编辑:sn-p:
concurrencySemaphore.Wait(cancelToken);
deferRelease = false;
try
{
var result = GetWorkItem();
if (result == null)
{ // no work, wait for new work or exit signal
signal = WaitHandle.WaitAny(signals);
continue;
}
deferRelease = true;
tasks.Add(Task.Factory.StartNew(() =>
{
try
{
DoWorkHereAsync(result); // guess I'd think to .GetAwaiter().GetResult() here.. not run this yet
}
finally
{
concurrencySemaphore.Release();
}
}, cancelToken));
}
finally
{
if (!deferRelease)
{
concurrencySemaphore.Release();
}
}
【问题讨论】:
-
另外,如果您担心并发限制和异步,为什么不改用 TPL DataFlow?它允许您限制每个图形组件,并且与
async/await兼容,非常适合 IO 绑定调用,而不是重新发明轮子 -
如果您的
StartNew以await semaphore.WaitAsync开头 - 如果您是这个意思,它在等待时不会保留此线程。因此,如果您将许多此类任务排队 - 它甚至可能不会在线程池中创建额外的线程。 -
我添加了一些代码 @MickyD 。我在尝试从队列中读取工作之前等待信号量,并没有想到 TPL DataFlow 但会看一下..如果它看起来仍然相关?
-
谢谢你的代码。
-
@Evk 我的主要问题是在同步委托中包装异步处理程序的感知狡猾,只是为了包装新任务。我想我可能错过了 Task.Run 和似乎需要异步委托的重载。我想我想
async完成我的包装任务和awaitDoWorkHereAsync..
标签: c# .net asynchronous task task-parallel-library