我正在尝试为Web应用程序开发一个上下文系统,它将沿着逻辑控制流传播数据。这类似于描述enter link description here的AsyncLocal堆栈。
最初,我只是使用LogicalCallContext来执行此操作,但这会遇到ASP.NET线程敏捷性问题。为了解决这个问题,我实现了一个混合系统,它使用逻辑调用上下文和HttpContext.Items。使用这个系统,我们保持两个上下文同步(假设它们都可用),并信任逻辑调用上下文,除非它丢失并且HttpContext.Items中有一些内容。
这几乎适用于所有情况,但是在异步方法的前半部分会遇到麻烦,该方法是从同步方法调用的,我们在请求线程上但在不同的逻辑调用上下文中。这是一个例子:
// in BeginRequest
MyContext.Push("BeginRequest");
public ActionResult SomeAction()
{
// sometimes Asp.NET does a thread switch between begin request and the action
// in that case, we have:
// Logical: null
// HttpContext: "BeginRequest"
var result = this.DoSomethingAsync().Result;
// Here we have
// Logical: null
// THIS IS WRONG: the logical context was correctly restored by async magic, but we
// corrupted the HttpContext. Since we lost the logical call context, we can't use that
// HttpContext: "DoSomethingAsync" -> "BeginRequest"
}
private async Task DoSomethingAsync()
{
// right now we're on the request thread, so we still have HttpContext but
// because we have a logical call context
// I would like to detect when the code is in THIS STATE
MyContext.Push("DoSomethingAsync");
// Here we have
// Logical: "DoSomethingAsync" -> "BeginRequest"
// HttpContext: "DoSomethingAsync" -> "BeginRequest"
// because this method does ConfigureAwait(false), on the other side of await
// you won't have the context
await ComputeSomethingAsync().ConfigureAwait(false);
// Here we have
// Logical: "DoSomethingAsync" -> "BeginRequest"
// HttpContext: null
MyContext.Pop();
// Here we have
// Logical: "BeginRequest"
// HttpContext: null
}
有没有办法检测到这种状态?是否有另一种方法可以在ASP.NET / .NET 4.5中获得一致的逻辑上下文流?