调用内部ASP.NET异步方法时,混乱的行为(Confusing behaviour when in

2019-09-23 09:18发布

我创建了使用Visual Studio 2012的ASP WebApplication的。

如果我修改了默认页面,如下所示:

public partial class _Default : Page
{
    static async Task PerformSleepingTask()
    {
        Action action = () =>
        {
            Thread.Sleep(TimeSpan.FromSeconds(0.5));
            int dummy = 3; // Just a nice place to put a break point
        };
        await Task.Run(action);
    }


    protected void Page_Load(object sender, EventArgs e)
    {
        Task performSleepingTask = PerformSleepingTask();
        performSleepingTask.Wait();
    }
}

在电话会议中performSleepingTask.Wait()它无限期地挂起。


有趣的是,如果我设置在web.config:

<appSettings>

    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="false" />
</appSettings>

然后它的工作。 在Wait函数等待睡眠,以在不同的线程完成,然后继续。


有人能解释一下:

  • 为什么它挂?
  • 为什么他们有一种称为TaskFriendlySynchronizationContext ? (由于它会导致任务挂起,我不会把它称为“友好”)

  • 是否有一个“最佳实践”为调用async从页面处理方法的方法呢?

这是我想出了其工作的实施,但感觉像笨拙的代码:

    protected void Page_Load(object sender, EventArgs e)
    {
        ManualResetEvent mre = new ManualResetEvent(false);
        Action act = () =>
        {
            Task performSleepingTask = PerformSleepingTask();
            performSleepingTask.Wait();
            mre.Set();
        };
        act.BeginInvoke(null, null);
        mre.WaitOne(TimeSpan.FromSeconds(1.0));
    }

Answer 1:

为什么它挂?

Task代表PerformSleepingTask尝试它后恢复await使PerformSleepingTask可以返回。 它试图重新进入ASP.NET请求上下文,这是由呼叫阻塞来Wait 。 这将导致死锁,因为我阐述我的博客上 。

为了避免死锁,请按照下列最佳做法:

  1. 使用async一路下跌。 不要阻止async代码。
  2. 使用ConfigureAwait(false)在您的“库”的方法。

为什么他们有一种称为TaskFriendlySynchronizationContext ? (由于它会导致任务挂起,我不会把它称为“友好”)

TaskFriendlySynchronizationContext使用新AspNetSynchronizationContext (在.NET 4.0 TaskFriendlySynchronizationContext已更名LegacyTaskFriendlySynchronizationContext ),并且它还采用了全新的, async知晓的管道。

我不是100%地肯定这一个,但我怀疑的理由Page_Load工程遗留SyncCtx是旧管道并没有把SyncCtx到位呢。 我不知道为什么会这样的行为,虽然(除非Page.Asyncfalse )。

是否有一个“最佳实践”从页面处理方法调用异步方法?

当然 。 您可以只让你的事件处理async void ,或使用RegisterAsyncTask(new PageAsyncTask(...)); 。 第一种方法是比较容易,但第二种方法是由ASP.NET团队的青睐。



文章来源: Confusing behaviour when invoking async methods inside ASP.NET