如果在使用ConfigureAwait(false)的引用库中使用Thread.CurrentPrincipal的声明是否会带来任何问题,或者ExecutionContext的逻辑调用上下文的流动是否会在那里照顾我?(我的阅读和测试迄今表明它会)。
示例WebAPI Controller操作:
[CustomAuthorizeThatSetsCurrentUsersClaimsToThreadCurrentContextAndHttpContextCurrentUser]
public async Task<Order> Get(int orderId)
{
return await _orderBusinessLogicLibrary.LoadAsync(orderId); // defaults to .ConfigureAwait(true)
}
示例从外部引用库加载函数:
[ClaimsPrincipalPermission(
SecurityAction.Demand,
Operation="Read",
Resource="Orders")]
[ClaimsPrincipalPermission(
SecurityAction.Demand,
Operation="Read",
Resource="OrderItems")]
public async Task<Order> Load(int orderId)
{
var order = await _repository.LoadOrderAsync(orderId).ConfigureAwait(false);
// here's the key line.. assuming this lower-level function is also imposing
// security constraints in the same way this method does, would
// Thread.CurrentPrincipal still be correct inside the function below?
order.Items = await _repository.LoadOrderItemsAsync(orderId).ConfigureAwait(false);
return order;
}
另外,答案不能只是“那就别用ConfigureAwait(false)!”这样会导致其他问题,比如死锁(不要在异步代码中阻塞)。
ConfigureAwait(false)
避免死锁的评论是特定于使用.Result
在异步方法上阻塞吗?所以,你不应该切换从ConfigureAwait(true)
到ConfigureAwait(false)
来解决死锁,你应该使整个栈完全异步,并且仍然希望ASP.NET等待中的ConfigureAwait(true)
以完全恢复HttpContext等。 - Madeline TrotterConfigureAwait
的默认值是true
。因此,如果你的async
方法需要上下文,则应该完全不使用ConfigureAwait
。如果它不需要上下文,则应该使用ConfigureAwait(false)
。我建议让整个堆栈都是async
,并且在任何不需要上下文的方法上也使用ConfigureAwait(false)
。 - Stephen Cleary