异步.NET控制台程序中的线程控制流 [英] Thread control flow in async .NET Console program

查看:109
本文介绍了异步.NET控制台程序中的线程控制流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C#中搞乱了async / await,只是想深入研究一些线程控制流,偶然发现了一个不寻常的行为,对此我非常感谢您进行澄清。
有意义的是,即使Task本身在后台执行,等待后的执行仍在调用线程上进行。实际上,这就是WPF所发生的。

以下代码:

I was messing around with async/await in C# just to dig into some of the thread control flow and stumbled upon an unusual behavior that I would really appreciate clarification on. It would make sense that the execution after await continues on a calling thread even if the Task itself was executed in background. And in fact that's exactly what happens with, let's say, WPF.
The following code:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    Console.WriteLine($"Start. Thread: {Thread.CurrentThread.ManagedThreadId}");
    await Task.Run(async () => await Task.Delay(1000));
    Console.WriteLine($"End. Thread: {Thread.CurrentThread.ManagedThreadId}");
}

结果出现在:

开始。线程:1

结束。线程:1


我意识到那是使程序流可预测的方法。


但是让我惊讶的是异步Main .NET Console应用程序的方法功能显示出一些不同的行为。

相同的代码:

Results in:
Start. Thread: 1
End. Thread: 1

I realize that that's the way to make the program flow predictable etc.

But what surprised me is that the async Main method feature of .NET Console applications shows somewhat different behavior.
The same code:

static async Task Main(string[] args)
{
    Console.WriteLine($"Start. Thread: {Thread.CurrentThread.ManagedThreadId}");
    await Task.Run(async () => await Task.Delay(1000));
    Console.WriteLine($"End. Thread: {Thread.CurrentThread.ManagedThreadId}");
}

导致不同的线程控制流:

开始。线程:1

结束。线程:5


我的猜测是,控制台应用程序具有同步上下文的不同概念,并且不像WPF那样绑定到主 UI线程。但是我实际上正在努力寻找一些明确的信息。

Results in a different thread control flow:
Start. Thread: 1
End. Thread: 5

My guess is that the console application has a different concept of a synchronization context and are not bound to a main "UI" thread unlike WPF. But i'm actually struggling to find some clear info apropos of this.

推荐答案

总之,当 SynchronizationContext.Current ,(在控制台应用程序中就是这种情况)。在 ThreadPool 上调用await响应。

In short, When the SynchronizationContext.Current not is set, (which is the case on a console application). The await response is invoked on the ThreadPool.

在Winforms / WPF上,实现了SynchronizationContext来将对Winforms controlToSendTo.BeginInvoke();的响应排队; 或WPF Dispatcher.BeginInvoke();

On a Winforms/WPF a SynchronizationContext is implemented to queue the response to either the winforms controlToSendTo.BeginInvoke(); or the WPF Dispatcher.BeginInvoke();.

参考:


但是有一种没有 SynchronizationContext 的常见应用程序:控制台应用程序。调用控制台应用程序的 Main 方法时, SynchronizationContext.Current 将返回 null 。这意味着,如果您在控制台应用程序中调用异步方法,则除非您执行特殊操作,否则您的异步方法将不会具有线程亲和力:这些异步方法中的继续操作可能最终在任何地方运行。

But there's one common kind of application that doesn't have a SynchronizationContext: console apps. When your console application's Main method is invoked, SynchronizationContext.Current will return null. That means that if you invoke an asynchronous method in your console app, unless you do something special, your asynchronous methods will not have thread affinity: the continuations within those asynchronous methods could end up running "anywhere."


  • 并行计算-一切都与SynchronizationContext 有关(文章引用了 SynchronizationContext 类的官方文档):

  • Parallel Computing - It's All About the SynchronizationContext (an article referenced from the official documentation for the SynchronizationContext class):


    默认情况下,控制台应用程序和Windows Services中的所有线程仅具有默认的 SynchronizationContext

    ...

    图4 SynchronizationContext摘要实现

    ...

    Figure 4 Summary of SynchronizationContext Implementations
    ...

    ╔═════════╦═══════════╦════════════╦════════════╦══════════╦══════════╗
    ║         ║ Specific  ║ Exclusive  ║ Ordered    ║ Send May ║ Post May ║
    ║         ║ Thread    ║ (Delegates ║ (Delegates ║ Invoke   ║ Invoke   ║
    ║         ║ Used to   ║ Execute    ║ Execute    ║ Delegate ║ Delegate ║
    ║         ║ Execute   ║ One at     ║ in Queue   ║ Directly ║ Directly ║
    ║         ║ Delegates ║ a Time)    ║ Order)     ║          ║          ║
    ╠═════════╬═══════════╬════════════╬════════════╬══════════╬══════════╣
    ║ ...     ║           ║            ║            ║          ║          ║
    ╠═════════╬═══════════╬════════════╬════════════╬══════════╬══════════╣
    ║ Default ║ No        ║ No         ║ No         ║ Always   ║ Never    ║
    ╚═════════╩═══════════╩════════════╩════════════╩══════════╩══════════╝



  • 这篇关于异步.NET控制台程序中的线程控制流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆