本文介绍了完成任务时手动捕获和应用SynchronizationContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在等待挂起时遇到问题(描述为).在研究过程中,我发现在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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 06:22
查看更多