繁体   English   中英

在转移到与调用方相同的线程之前(对于UI应用程序),是否在内部创建另一个线程

[英]Does await create another thread internally before shifting to the same thread as the caller (for UI application)

我对async / await的了解是,当任务完成时,继续在调用await的同一上下文中运行,就我而言,这就是UI线程。 但是我的问题是,它会在IO完成之后并移至相同的UI线程之前(内部)创建一个新线程。

我正在共享一段代码。 如果单击一次此按钮,则表明执行等待之前可用线程为1023,但此后,可用线程降至1022。尽管当我检查线程ID时,它与UI线程相同。

    private async void button1_ClickAsync(object sender, EventArgs e)
    {
        int x, y;
        ThreadPool.GetAvailableThreads(out x, out y);
        textBox1.Text = x.ToString()+"..."+y.ToString();
        await Task.Delay(5000);
        ThreadPool.GetAvailableThreads(out x, out y);
        textBox1.Text = x.ToString() + "..." + y.ToString();
    }

但是有趣的是,下次我单击该按钮时,可用线程数仍为1023(在等待之前和之后)。

但是我的问题是,它会在IO完成之后并移至相同的UI线程之前(内部)创建一个新线程。

可能会暂时使用其他线程,但是您不必为此担心。

特别是,.NET上的I / O通常通过作为线程池一部分的I / O完成端口。 I / O线程会根据需要自动添加和删除。 通常,在I / O实际准备好返回到代码之前(例如,解析HTTP响应标头),还有很多其他工作要做,因此许多 BCL I / O代码实际上将使用I / O线程只是将工作排队到线程池中。 因此,I / O代码经常(简短地)使用线程池工作线程。

另外,在这个特定的示例中,我相信还有一个单独的计时器线程可以合并系统计时器。 自然,这是一个实现细节,并且随时可能更改。

因此,总而言之,可能会创建/销毁/临时使用其他线程,但是您不必为此担心。 它们全部由BCL或.NET运行时以非常有效的方式进行管理,从而在重用线程(最小化搅动)和最小化资源使用(尤其是内存)之间取得平衡。

我猜你的意思是下降到1022。

一般来说,我认为这取决于进行的异步调用。 磁盘和网络调用将从I / O完成线程池中的线程返回。 看来Task.Delay在常规工作线程上返回。

您可以将行更改为await Task.Delay(5000).ConfigureAwait(false); ,在其后设置一个断点,并检查“线程”窗口以直接查看此断点。

无论您从哪里调用它,它都将在工作线程上完成。 await不会将调用上下文传递给实现异步操作的函数; 完成后,它仅添加返回UI线程的额外步骤。

在这里跟踪确切的数字我不会读太多。 CLR具有自己的算法来管理线程池大小,并且这些算法可以随版本的不同而变化。 而且我不会在那使用其他线程来强调它:在普通应用程序中,它将仅重用池中的现有线程,并且操作将非常快。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM