问题描述
我在等待挂起时遇到问题(描述为).在研究过程中,我发现在TaskCompletionSource
上调用SetResult
实际上会在名为SetResult
的线程的上下文中调用等待继续(在).在我的情况下,这是与启动等待(ASP.NET请求线程)的线程不同的线程(线程池工作线程).
I was having a problem with a hanging await (described here). During research I found out that calling SetResult
on my TaskCompletionSource
actually invokes awaiting continuation in the context of the thread that called SetResult
(this is also spelled out in this answer to a somewhat related question). In my case this is a different thread (a thread-pool worker thread) from the one that started the await (an ASP.NET request thread).
虽然我仍然不确定为什么会导致挂起,但我决定尝试将SetResult
强制进入原始上下文.我在请求线程上输入await之前存储了SynchronizationContext.Current
的值,并在调用SetResult
之前通过SynchronizationContext.SetSynchronizationContext
将其手动应用于工作线程中.这样就解决了挂起的问题,现在我可以等待所有异步方法,而不必指定ConfigureAwait(false)
.
While I'm still not sure why this would cause a hang, I decided to try forcing the SetResult
into the original context. I stored the value of SynchronizationContext.Current
before entering await on the request thread and manually applied it in the worker thread via SynchronizationContext.SetSynchronizationContext
just before calling SetResult
. This solved the hang and I can now await all my async methods without having to specify ConfigureAwait(false)
.
我的问题是:这是手动捕获和应用SynchronizationContext
的合理且正确的方法吗? FWIW,我尝试首先使用SetResult
委托进行简单的Post()
,但这仍然导致挂起.很显然,我在这里超出了我的舒适范围……请帮助我了解发生了什么事!
My question is: is this a reasonable and correct approach to manually capturing and applying the SynchronizationContext
? FWIW, I tried doing a simple Post()
with the SetResult
delegate first, but that still caused a hang. I'm obviously a bit out of my comfort zone here... Please help me understand what's going on!
推荐答案
令我尴尬的是,我完全忽略了我的HTTP处理程序是从一个小的基类派生的,该基类以一种非常可疑的方式实现了IAsyncHttpHandler
,以便添加对异步处理程序的支持:
To my embarrassment, I had completely overlooked that my HTTP handler was derived from a small base class, which implemented IAsyncHttpHandler
in a very questionable way in order to add support for async handlers:
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
...
var task = HandleRequestAsync(...);
Task.Run(async () => { await task; }).GetAwaiter().GetResult();
...
}
我什至不记得为什么我要这样做(一年多以前),但这绝对是我最近几天一直在寻找的 愚蠢的部分!
I can't even remember why I did this in the first place (it was over a year ago), but it definitely was THE stupid part I was looking for for the last couple of days!
将处理程序基类更改为.NET 4.6的HttpTaskAsyncHandler
摆脱了挂起.很抱歉浪费大家的时间! :(
Changing the handler base class to .NET 4.6's HttpTaskAsyncHandler
got rid of the hangs. Sorry for wasting everyone's time! :(
这篇关于完成任务时手动捕获和应用SynchronizationContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!