AsyncLocal允许我们将上下文数据保留在异步控制流中。这非常好,因为所有后续简历(甚至在另一个线程上)都可以检索和修改环境数据(AsyncLocal on MSDN)。

有什么方法可以为子任务“离开”当前异步本地上下文,从而创建一个新的子任务?

AsyncLocal<string> Data = new AsyncLocal<string>();
Data.Value = "One";

Task.Factory.StartNew( () =>
{
    string InnerValue = Data.Value;
    //InnerValue equals to "One", I need it to be null.
} );

在上面的示例中,内部任务与外部控制流共享AsyncLocal上下文。有什么方法可以强制执行新的环境?

更新:为了在这里解决我的问题,以下代码起了很大的作用(尽管它并没有完全重置上下文):
AsyncLocal<string> Data = new AsyncLocal<string>();
Data.Value = "One";

Task.Factory.StartNew( () =>
{
    Data.Value = null;
    string InnerValue = Data.Value;
    //InnerValue equals to null now.
} );

string OuterValue = Data.Value; //Stays "one" even after the inner change.

最佳答案

您可以使用 ExecutionContext.SuppressFlow :

AsyncLocal<string> Data = new AsyncLocal<string>();
Data.Value = "One";

using (ExecutionContext.SuppressFlow())
{
    Task.Factory.StartNew( () =>
    {
        string InnerValue = Data.Value;
        //InnerValue is null.
    } );
}

请注意,这可能会产生副作用,例如不再产生正确的堆栈跟踪。但是,由于您忽略了StartNew的结果,即您似乎对实际拥有流程不感兴趣,因此这是正确的做法。

另外,为了更符合您自己的更新中的解决方案,请记住AsyncLocal是作用域的,即,如果您在嵌套异步操作中设置该值,则它不会影响外部函数中的值。这意味着您可以在嵌套操作中重置AsyncLocal的第一件事,而不会破坏外部操作的值。

关于c# - C#异步/等待:创建任务后保留AsyncLocal <T>上下文,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35826893/

10-10 03:12