在.net 4.7中使用LegacyAspNetSynchronizationContext对async / await



我正在将一个遗留的 Asp.Net WebForms 项目升级到 .net 4.7。

在我的配置中,我将目标框架设置为 4.7 和同步上下文以使用新的AspNetSynchronizationContext(尽管我相信如果省略后者是隐含的)以允许新的async / await方法工作,例如

<httpRuntime targetFramework="4.7" />
...
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

但后来我发现很多代码如下:

var myTask = DoSomethingAsync();
return myTask.Result;

未等待任务的结果,这会导致应用挂起。

如果我更改配置以使用LegacyAspNetSynchronizationContext...

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

。旧的非等待代码再次工作,新的async/await方法似乎有效。我说"出现",因为我在这篇 MSDN 文章中读到:

异步

/等待的行为在 ASP.NET 中未定义,除非已设置此开关

为什么它未定义?这是否意味着行为是不可预测的或根本不起作用?

如果我有如下所示的代码片段,那么在LegacyAspNetSynchronizationContext中调用它时会发生什么或可能发生什么?

public async Task<bool> DoSomethingElseAsync()
{
return await CallSomeApiAsync().ConfigureAwait(false);
}

使用LegacyAspNetSynchronizationContext意味着在使用任务时不会获得定义的行为;旧版同步模型不是为使用任务调度而构建的。如果要在 ASP.NET 中使用任务,则必须使用新的同步上下文。

var myTask = DoSomethingAsync();
return myTask.Result;

此代码在Task上阻止。在正在运行的Task上调用Wait()Result将阻塞调用线程,直到Task完成。

除非您知道以下信息,否则无法安全地阻止任务:

  • 任务已经完成(在这种情况下,您并没有真正阻止)。
  • 同步上下文不会尝试在启动任务的同一线程上恢复。

唯一合理的解决方案是一直使用任务。任何试图阻止Task的方法都应该改为返回TaskTask<TResult>,并改为await正在运行的Task

相关内容

  • 没有找到相关文章

最新更新