C#Async/Await:在创建任务时保留AsyncLocal <T>上下文

Sim*_*tes 15 .net c# asynchronous

AsyncLocal允许我们将上下文数据保存在异步控制流上.这非常简洁,因为以下所有简历(即使在另一个线程上)都可以检索和修改环境数据(MSDN上的AsyncLocal).

有没有办法'离开'子任务的当前异步本地上下文,从而创建一个新的?

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.
} );
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,内部任务与外部控制流共享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.
Run Code Online (Sandbox Code Playgroud)

Seb*_*edl 10

您可以使用ExecutionContext.SuppressFlow

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

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

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

或者,更符合您自己更新中的解决方案,请记住它AsyncLocal是有范围的,即如果您在嵌套异步操作中设置值,它不会影响外部函数中的值。这意味着您可以AsyncLocal在嵌套操作中首先重置,而不会破坏外部操作的值。