是否可以强制继续使用async-await语句在自定义ThreadPool的线程上运行?
背景信息:我正在运行ASP应用程序并在后台完成相当多的工作。我通过自编写的ThreadPool完成所有工作,但是如果我使用async-await模式,则延续始终在名为" Worker Thread"的线程上运行。 我非常确定这是来自默认ThreadPool的线程,它也用于处理HTTP请求。 由于默认ThreadPool的所有线程都忙着继续我的后台工作,这导致这些请求的饥饿。
答案 0 :(得分:5)
是。您可以创建适用于自定义ThreadPool
的自定义SynchronizationContext
,并在运行异步操作之前对其进行设置。
var prevCtx = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(new ThreadPoolSynchronizationContext());
// async operations.
}
finally
{
SynchronizationContext.SetSynchronizationContext(prevCtx);
}
有关如何创建自定义SynchronizationContext
的更多信息:Await, SynchronizationContext, and Console Apps
虽然很少需要自定义ThreadPool。您可能应该尝试使用内置的优化进行优化。
答案 1 :(得分:4)
我认为您不需要自定义线程池,特别是如果您正在进行大量自然使用IOCP线程的并行I / O.这适用于任何其他只在任务完成时从池中获取线程的API(例如Task.Delay
)。
通常你会await task.ConfigureAwait(false)
继续在task
完成的同一个帖子上发生:
// non-IOCP (worker) continuation thread
await Task.Delay(1000).ConfigureAwait(false);
// IOCP continuation thread
await stream.ReadAsync(buff, 0, buff.Length).ConfigureAwait(false);
现在,在ASP.NET中,您甚至不需要使用ConfigureAwait
。 ASP.NET AspNetSynchronizationContext
没有为await
延续保持线程关联,与 WinFormsSynchronizationContext
或DispatcherSynchronizationContext
不同UI应用。您的延续将在任务已完成的任何线程上运行,原样。 AspNetSynchronizationContext
只是"进入"该线程上的ASP.NET上下文,以确保您的代码可以访问HttpContext
和其他相关的ASP.NET请求环境状态信息。
您可以将ThreadPool.SetMinThreads
的默认IOCP和工作线程数增加到ThreadPool
stuttering problems。
如果自定义线程池的唯一原因是限制任务的并行度,请使用TPL数据流或仅SemaphoreSlim.WaitAsync
(检查"Throttling asynchronous tasks")。
也就是说,如果实现自定义等待,您可以非常精确地控制Task
延续。检查this question以获取该基本示例。