当你有服务器端代码(即一些ApiController)并且你的函数是异步的 - 所以它们返回Task<SomeObject>- 你认为最好的做法是等待你调用的函数ConfigureAwait(false)吗?
我已经读过它更高效,因为它不必将线程上下文切换回原始线程上下文.但是,使用ASP.NET Web Api,如果您的请求是在一个线程上进行的,并且等待某些函数和调用ConfigureAwait(false),则可能会在返回ApiController函数的最终结果时将您置于不同的线程上.
我在下面输入了一个我正在谈论的例子:
public class CustomerController : ApiController
{
public async Task<Customer> Get(int id)
{
// you are on a particular thread here
var customer = await SomeAsyncFunctionThatGetsCustomer(id).ConfigureAwait(false);
// now you are on a different thread! will that cause problems?
return customer;
}
}
Run Code Online (Sandbox Code Playgroud) 我在GitHub上偶然发现了一个问题(https://github.com/HTBox/allReady/issues/1313),在那里他们讨论了如何ConfigureAwait(false)在ASP.NET核心中删除代码
呼叫
ConfigureAwait(false)是多余的,什么都不做
我能找到的最好的答案是一个"旁注"(来自Stephen Cleary,https: //stackoverflow.com/a/40220190/2805831 )
ASP.NET Core不再具有"上下文"
那么,ASP.NET Core中ConfigureAwait(false)真的没必要(即使使用完整的.Net Framework)?在某些情况下,它在性能方面是否有任何实际的好处,或者在结果/语义上有所不同?
编辑:如果我将其作为控制台应用程序托管或在IIS中,它在这方面有所不同吗?
如果在ASP.NET MVC中执行以下代码,您可以在调试窗口中看到await,即使ManagedThreadId发生更改,它也会正确恢复该文件的文化:
public async Task<ActionResult> Index()
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
Debug.WriteLine(Thread.CurrentThread.CurrentUICulture);
await SomeMethod();
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
Debug.WriteLine(Thread.CurrentThread.CurrentUICulture);
return View();
}
private async Task SomeMethod()
{
await Task.Delay(100).ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)
然后我将ConfigureAwait(false)从SomeMethod()移动到Index(),除此之外,它与上面的代码相同:
public async Task<ActionResult> Index()
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("de-DE");
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
Debug.WriteLine(Thread.CurrentThread.CurrentUICulture);
await SomeMethod().ConfigureAwait(false);
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
Debug.WriteLine(Thread.CurrentThread.CurrentUICulture);
return View();
}
private async Task SomeMethod()
{
await Task.Delay(100);
}
Run Code Online (Sandbox Code Playgroud)
现在它不会恢复我的文化,但始终将其设置为new CultureInfo("en-US").但我希望使用这两种方法,结果必须相同.它绝对不清楚,为什么会发生这种情况.
我正在检查一些使用 .NET 4.7.2 的 ASP.NET Web API 代码。
这是一个示例控制器和操作方法:
public class ThingController : System.Web.Http.ApiController
{
// ...
public async Task<IHttpActionResult> GetValue()
{
var value = await _db.GetValue().ConfigureAwait(false);
return Content(value);
}
}
Run Code Online (Sandbox Code Playgroud)
我读到,最佳实践是不在ConfigureAwait应用程序代码中使用,以便继续执行捕获的同步上下文,因为可能存在与捕获的上下文关联的所需状态。然而,一般来说,我们应该使用ConfigureAwait(false)这样的方法,这样我们就不会不必要地继续捕获的同步上下文。
所以我的想法是,我们不想ConfigureAwait(false)在此 Web API 代码中的任何位置进行调用。
然后我读到了有关死锁的内容,并且在使用 ASP.NET Core 时这并不重要(尽管我不是)。
我添加了一个断点并检查了SynchronizationContext.Current哪个是null.
ConfigureAwait(false)我可以安全地删除该项目的所有调用吗?如果不是,在什么情况下应该保留这些调用?