在另一个线程上继续时异步

时间:2018-06-29 19:40:38

标签: c# async-await thread-safety task memory-barriers

我知道一个Task可能会在此代码证明的另一个线程上继续执行。

    public async Task Test()
    {
        var id1 = System.Environment.CurrentManagedThreadId;
        await Task.Delay(1000);
        var id2 = System.Environment.CurrentManagedThreadId;
        Console.Write($"First {id1} then {id2}");
    }

我希望该框架能够处理内存障碍,以便在最后一条语句中访问id1时可见。

但是如果您使用某种框架,例如NHibernate,其中ISession不是线程安全的。框架甚至可以检查线程ID是否相同。如何混合?

建立网站时,我将使用每个请求带有嵌套容器的IOC容器,但是当线程可以在同一请求内更改时,这是否会导致各种问题? ThreadStatic无法正常工作

1 个答案:

答案 0 :(得分:0)

不是线程安全的通常意味着不要同时在多个线程中使用它,而不是在一个线程中使用它,然后再在另一个线程中使用它。

我不太了解NHibernate,但是如果有问题,请考虑使用EF Core。

通常对于异步,不要使用附加到特定线程的变量,例如线程本地或线程静态。

但是,局部变量,类成员,逻辑调用上下文,HttpContext(如果您位于asp.net上)等继续起作用。如果在await之后确实丢失了某些内容,通常可以先将其保存到本地变量中。

默认的ConfigureAwait(true)还会在延续中恢复一些上下文,但是很难知道恢复了什么,没有恢复什么。更高版本的.net在此方面做得更好,例如恢复了区域性,以便资源在await之后继续工作。

斯蒂芬·图卜(Stephen Toub)在这里有一篇很好的文章: https://blogs.msdn.microsoft.com/pfxteam/2012/06/15/executioncontext-vs-synchronizationcontext/