首页 文章

异步方法在哪里运行?

提问于
浏览
1

我已经阅读了很多关于async-await模式的文章,但我仍然不确定 whether the async methods (the awaited methods) run on the UI thread or not . 我总是以SynchronizationContext类结束"async methods run in the same SynchronizationContext with the callee"这究竟是什么意思?

它是新创建的单独线程(我知道它不是)还是ThreadPool线程?

当我读取SynchronizationContext时,我发现它是某种排队的任务 Actuator ,但这些任务在哪里执行?在ThreadPool上?

如果是,则在ThreadPool上执行异步方法,对吧?

2 回答

  • 3

    标记为 async 的方法在调用它的线程上运行,直到它到达其中的第一个 await 关键字 .

    但有一个例外:如果等待的方法在到达 await 关键字时已经完成运行,则执行只是在不切换线程的情况下继续执行 .

    public async Task Method()
    {
        Console.WriteLine(1);
        await Something();
        Console.Writeline(2);
    }
    

    在这种情况下,如果在线程A上调用该方法,那么也将从线程A打印1 .

    然后你转到下一条指令 . 如果 something 返回的 Task 已经完成,则在线程A上继续执行 . 如果 something 返回的 Task 仍在运行,则可以从以下任意一个打印2:

    • 线程A再次 - 如果有一个SynchronizationContext强制执行此操作(如在WPF或WinRT应用程序中) . 简单地说,这是通过排队和调度要在线程A上执行的剩余代码(即第三条指令)来完成的 .

    • 在一个完全不同的线程B.


    关于你对ThreadPool的疑虑:

    正如我们所看到的, async 方法不能保证在ThreadPool上运行 . 只有一个 Task.Run 重载方法安排的工作肯定会在ThreadPool上运行 . 引用 Task MSDN doc:

    将指定的工作排队到ThreadPool上运行并返回该工作的任务句柄 .

    public void Task Something()
    {
        return Task.Run(() => Console.WriteLine(3));
    }
    

    3将由ThreadPool上的一个线程打印 .

  • 4

    我已经阅读了很多关于async-await模式的文章,但我仍然不确定异步方法(等待的方法)是否在UI线程上运行 .

    如果您还没有,请查看我的async intro post,它解释了 asyncawait 的线程行为 .

    当您调用 async 方法时,它会在第一次 await 不完整的操作时同步执行 . 然后 async 方法捕获当前的"context"并调度其余部分以便稍后执行,然后返回 .

    稍后,当操作完成时, async 方法的其余部分将安排在捕获的"context"上运行 .

    "context"是当前的 SynchronizationContext ,除非它是 null ,在这种情况下它是当前的 TaskScheduler . 当您从UI线程调用 async 方法时,您有一个UI SynchronizationContext ,它通过将工作发布到UI线程的消息循环来工作 .

相关问题