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

Async when continuing on another thread

我知道一个任务可能会在另一个线程上继续执行,由这段代码证明。

    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 无法按预期工作

非线程安全通常意味着不要从多个线程同时使用它,而不是不要从一个线程使用它,然后再从另一个线程使用它.

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

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

但是,局部变量、class 成员、逻辑调用上下文、HttpContext(如果你在 asp.net 上)等继续工作。如果你确实有一些东西在await之后会丢失,你通常可以先将它保存到一个局部变量中。

默认值 ConfigureAwait(true) 还会恢复一些关于延续的上下文,但很难知道什么恢复了,什么没有恢复。 .net 的更高版本在这方面做得更好,比如恢复文化,以便资源在 await.

之后继续工作

这里有一篇 Stephen Toub 的好文章: https://blogs.msdn.microsoft.com/pfxteam/2012/06/15/executioncontext-vs-synchronizationcontext/