退出异步方法可以将控制权转回到其他异步方法吗?

剃刀

我知道等待任务的异步将执行返回给调用方,使其继续执行直到需要结果为止。

在某种程度上,我对我的想法的解释是正确的。看起来好像发生了某种交错。我希望Do3()完成,然后将调用堆栈备份到Do2()。查看结果。

        await this.Go();

哪个电话

        async Task Go()
        {
            await Do1(async () => await Do2("Foo"));

            Debug.WriteLine("Completed async work");
        }

        async Task Do1(Func<Task> doFunc)
        {
            Debug.WriteLine("Start Do1");

            var t = Do2("Bar");

            await doFunc();

            await t;
        }

        async Task Do2(string id)
        {
            Debug.WriteLine("Start Do2: " + id);

            await Task.Yield();

            await Do3(id);

            Debug.WriteLine("End Do2: " + id);
        }

        async Task Do3(string id)
        {
            Debug.WriteLine("Start Do3: " + id);

            await Task.Yield();

            Debug.WriteLine("End Do3: " + id); // I did not expect Do2 to execute here once the method call for Do3() ended
        }

预期结果:

// Start Do1
// Start Do2: Bar
// Start Do2: Foo
// Start Do3: Bar
// Start Do3: Foo
// End Do3: Bar
// End Do2: Bar
// End Do3: Foo
// End Do2: Foo
//Completed async work

实际输出:

//Start Do1
//Start Do2: Bar
//Start Do2: Foo
//Start Do3: Bar
//Start Do3: Foo
//End Do3: Bar
//End Do3: Foo
//End Do2: Bar
//End Do2: Foo
//Completed async work

到底是怎么回事?

我正在使用.NET 4.5和一个简单的WPF应用程序来测试我的代码。

鼻塞

这是一个WPF应用程序,所有这些代码都在同一UI线程上执行。await您代码中的每个延续都通过进行安排DispatcherSynchronizationContext.Post,该过程将特殊的Windows消息发布到UI线程的消息队列中。每个延续都按其消息发布的顺序发生(这是特定于实现的,您不应该依赖于此,但这就是这里的工作方式)。

因此,的延续End Do3: Foo实际上是在的之后End Do3: Bar输出正确。

现在,更多细节。当我询问WinForms vs WPF时,我希望您的“预期”输出与实际输出匹配。我刚刚在WinForms下对其进行了测试,它确实匹配:

// Start Do1
// Start Do2: Bar
// Start Do2: Foo
// Start Do3: Bar
// Start Do3: Foo
// End Do3: Bar
// End Do2: Bar
// End Do3: Foo
// End Do2: Foo
//Completed async work

那么,为什么WPF和WinForms之间的差异,尽管两者都运行消息循环,而我们在这里只处理单线程代码?答案可以在这里找到:

为什么每个Dispatcher.BeginInvoke回调都具有唯一的同步上下文?

WPFDispatcherSynchronizationContext.Post只是调用Dispatcher.BeginInvoke,而WPF的一个重要实现细节是每个Dispatcher.BeginInvoke回调都在其自己的唯一同步上下文上执行,如链接的问题所述。

这会影响对象(如await延续在WinForms中,这样的连续是内联的(同步执行),因为保持不变。在WPF中,他们没有内联,但通过比较贴,因为之前和完成后是不一样的(它被里面比较运行时基础结构代码)。Taskawait doFunc()SynchronizationContext.CurrentSynchronizationContext.PostSynchronizationContext.Current await tasktasktask.GetAwaiter().OnCompletedawait

因此,在WPF中,它通常是相同的UI线程,但是与此线程关联的同步上下文不同,因此,继续操作可能会导致另一个异步PostMessage回调被消息循环发布,泵送和执行。除了YieldAwaitable(由返回Task.Yield),您还会遇到TaskCompletionSource.SetResultWPF UI线程触发的-style延续的这种行为

这是相当复杂但特定于实现的东西。如果要精确控制异步await继续的顺序,则可能需要推出自己的同步上下文,类似于Stephen Toub的AsyncPump尽管通常不需要,尤其是对于UI线程。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

异步方法不将控制权返回给调用者方法

来自分类Dev

异步方法不会将控制权返回给调用者

来自分类Dev

异步方法不会将控制权返回给调用者

来自分类Dev

程序在被调用方法完成之后会终止,还是将控制权返回给调用函数?

来自分类Dev

程序在被调用方法完成之后会终止,还是将控制权返回给调用函数?

来自分类Dev

我可以异步将webapp2.RequestHandler请求复制到其他网址吗?

来自分类Dev

Javascript异步功能如何在特定点显式产生控制权?

来自分类Dev

异步功能不会将控制权返回给主线程(linq表达式)

来自分类Dev

Python 解释器在异步操作中将控制权交还给 C 调用方

来自分类Dev

在ASP.net C#中,有没有一种方法可以将控制权从Javascript传递给CS?

来自分类Dev

在ASP.net C#中,有没有一种方法可以将控制权从Javascript传递给CS?

来自分类Dev

GetSchema方法可以异步工作吗?

来自分类Dev

使用线程时将控制权返回到Java中的主程序

来自分类Dev

使用线程时将控制权返回到Java中的主程序

来自分类Dev

Python显然继续无法将控制权返回到while循环

来自分类Dev

线程在调用方法之后但在该方法的第一条指令之前会失去控制权吗?

来自分类Dev

是否只有在调用了内部使用的所有回调之后,才可以使方法返回控制权?

来自分类Dev

在其他“异步”方法中“等待”方法是否合适

来自分类Dev

创建异步方法并设置其他方法的任务结果

来自分类Dev

在其他“异步”方法中“等待”方法是否合适

来自分类Dev

远程桌面,用户可以重新获得控制权吗?

来自分类Dev

有没有人有一个很好的例子说明如何使用super()将控制权传递给其他类?

来自分类Dev

除了在异步方法内调用ConfigureAwait(false)之外,还有其他更具可读性的方法吗?

来自分类Dev

有什么方法可以控制Javascript异步加载顺序?

来自分类Dev

在C#中使用DllImport的最佳方法以及如何从外部方法获取控制权

来自分类Dev

在C#中使用DllImport的最佳方法以及如何从外部方法获取控制权

来自分类Dev

使我的MVC异步控制器方法异步,以便它们可以同时处理

来自分类Dev

有什么方法可以异步等待Boost Asio的未来吗?

来自分类Dev

Azure WebJobs-我可以使用异步方法吗?

Related 相关文章

  1. 1

    异步方法不将控制权返回给调用者方法

  2. 2

    异步方法不会将控制权返回给调用者

  3. 3

    异步方法不会将控制权返回给调用者

  4. 4

    程序在被调用方法完成之后会终止,还是将控制权返回给调用函数?

  5. 5

    程序在被调用方法完成之后会终止,还是将控制权返回给调用函数?

  6. 6

    我可以异步将webapp2.RequestHandler请求复制到其他网址吗?

  7. 7

    Javascript异步功能如何在特定点显式产生控制权?

  8. 8

    异步功能不会将控制权返回给主线程(linq表达式)

  9. 9

    Python 解释器在异步操作中将控制权交还给 C 调用方

  10. 10

    在ASP.net C#中,有没有一种方法可以将控制权从Javascript传递给CS?

  11. 11

    在ASP.net C#中,有没有一种方法可以将控制权从Javascript传递给CS?

  12. 12

    GetSchema方法可以异步工作吗?

  13. 13

    使用线程时将控制权返回到Java中的主程序

  14. 14

    使用线程时将控制权返回到Java中的主程序

  15. 15

    Python显然继续无法将控制权返回到while循环

  16. 16

    线程在调用方法之后但在该方法的第一条指令之前会失去控制权吗?

  17. 17

    是否只有在调用了内部使用的所有回调之后,才可以使方法返回控制权?

  18. 18

    在其他“异步”方法中“等待”方法是否合适

  19. 19

    创建异步方法并设置其他方法的任务结果

  20. 20

    在其他“异步”方法中“等待”方法是否合适

  21. 21

    远程桌面,用户可以重新获得控制权吗?

  22. 22

    有没有人有一个很好的例子说明如何使用super()将控制权传递给其他类?

  23. 23

    除了在异步方法内调用ConfigureAwait(false)之外,还有其他更具可读性的方法吗?

  24. 24

    有什么方法可以控制Javascript异步加载顺序?

  25. 25

    在C#中使用DllImport的最佳方法以及如何从外部方法获取控制权

  26. 26

    在C#中使用DllImport的最佳方法以及如何从外部方法获取控制权

  27. 27

    使我的MVC异步控制器方法异步,以便它们可以同时处理

  28. 28

    有什么方法可以异步等待Boost Asio的未来吗?

  29. 29

    Azure WebJobs-我可以使用异步方法吗?

热门标签

归档