【问题标题】:What effect does using LegacyAspNetSynchronizationContext have with async / await code in .net 4.7?使用 LegacyAspNetSynchronizationContext 对 .net 4.7 中的 async / await 代码有什么影响?
【发布时间】:2018-07-26 07:25:15
【问题描述】:

我正在将旧的 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 方法出现 工作。我在this MSDN article 中读到时说“出现”:

除非已设置此开关,否则 ASP.NET 中未定义 async / await 的行为

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

如果我有如下的 sn-p 代码,当它在 LegacyAspNetSynchronizationContext 中调用时会发生什么或可能发生什么?

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

【问题讨论】:

  • “未定义”表示“尚未定义”。 ASP.NET 团队还没有正式定义系统应该做什么,所以你不能对你的代码做什么有任何期望。它可能工作正常,也可能什么都不做,它可能会导致您的服务器在 eBay 上出售自己。

标签: c# asp.net webforms async-await .net-4.7


【解决方案1】:

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

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

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

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

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

唯一合理的解决方案是一直使用任务。任何试图阻止 Task 的方法都应改为返回 TaskTask&lt;TResult&gt;await,而不是正在运行的 Task

【讨论】:

  • 谢谢@paul。我希望在涉及大量遗留代码的情况下,可能有一个替代 async 的方式。
猜你喜欢
  • 1970-01-01
  • 2019-03-24
  • 2012-05-26
  • 2015-07-04
  • 1970-01-01
  • 2017-12-05
  • 1970-01-01
  • 2019-01-10
  • 2022-01-22
相关资源
最近更新 更多