UI线程有什么特别之处?

use*_*580 6 c# multithreading async-await

假设我有一个fooCPU同步运行的方法(它不会调用执行I/O的纯异步方法,或者通过调用Task.Run或类似方式使用其他线程来运行其代码).该方法执行一些繁重的计算 - 它受CPU限制.

现在我调用fooCPU我的程序而不委托它由工作线程执行.如果一行fooCPU需要很长时间才能运行,那么在完成之前不会执行任何其他行.因此,例如,从UI线程调用它会导致UI线程冻结(GUI将变得无响应).

当我说这async/await是对多线程的模仿.两个不同代码的行在一个线程上轮流执行.如果这些行中的一行需要很长时间才能运行,则在完成之前不会执行任何其他行.,

我被告知在UI线程上使用async是正确的,但对于所有其他情况(ASP.NET,线程池上的异步,控制台应用程序等)并非如此.

谁能告诉我这可能意味着什么?UI线程与控制台程序的主线程有何不同?

我想在这个论坛上没有人希望任何人继续讨论相关主题,例如它们出现在评论中,所以最好提出一个新问题.

Han*_*ant 10

这很简单,一个线程一次只能做一件事.因此,如果您在森林中发送UI线程执行非UI相关的操作(例如dbase查询),则所有UI活动都会停止.没有更多的屏幕更新,没有响应鼠标点击和按键.它看起来和行为冻结.

你可能会说,"好吧,我只会用另一个线程来做UI".在控制台模式下工作,有点像.但不是在GUI应用程序中,使代码线程安全很困难,UI根本不是线程安全的,因为涉及的代码太多了.不是你写的那种,你用的是一种花哨的类库包装器.

通用的解决方案是反转它,在工作线程上执行非UI相关的东西,并让UI线程只处理简单的UI内容.Async/await帮助你做到这一点,await右边的内容在一个worker上运行.解决这个问题的唯一方法就是让UI线程仍然做太多工作.就像每毫秒一次向文本框添加一行文本一样.这只是糟糕的UI设计,人类不会那么快读.


Ste*_*ary 10

我建议你阅读我的async介绍帖 ; 它解释了asyncawait关键字的工作原理.然后,如果您对编写异步代码感兴趣,请继续阅读我的async最佳实践文章.

介绍的相关部分:

异步方法的开始就像任何其他方法一样执行.也就是说,它会同步运行,直到遇到"等待"(或抛出异常).

所以这就是你的控制台代码示例中内部方法(没有await)同步运行的原因.

等待检查等待它是否已经完成; 如果等待已经完成,那么该方法就会继续运行(同步,就像常规方法一样).

所以这就是你的控制台代码示例中外部方法(即await同步的内部方法)同步运行的原因.

稍后,当等待完成时,它将执行异步方法的剩余部分.如果您正在等待内置等待(例如任务),则异步方法的其余部分将在"await"返回之前捕获的"上下文"上执行.

这种"背景" SynchronizationContext.Current除非是null,否则就是这样TaskScheduler.Current.或者,更简单的版本:

究竟是什么"背景"?简单回答:

  1. 如果你在UI线程上,那么它就是一个UI上下文.
  2. 如果您正在响应ASP.NET请求,那么它是一个ASP.NET请求上下文.
  3. 否则,它通常是线程池上下文.

把所有这些放在一起,你可以想象async/ await像这样工作:方法被分成几个"块",每个块await作为分割方法的点.第一个块总是同步运行,并且在每个分割点它可以同步或异步地继续.如果它以异步方式继续,则它将在捕获的上下文中继续(默认情况下).UI线程提供将在UI线程上执行下一个块的上下文.

因此,回答这个问题,UI线程的特殊之处在于它们提供了一个SynchronizationContext队列工作回到同一个UI线程.

我想在这个论坛上没有人希望任何人继续讨论相关主题,例如它们出现在评论中,所以最好提出一个新问题.

好吧,Stack Overflow特别不是一个论坛; 这是一个问答网站.因此,它不是一个要求详尽的教程的地方; 当你试图让代码工作时,或者在你研究了所有关于它的一切之后你不理解某些东西时,它就是一个可以来的地方.这就是为什么关于SO的评论被(有目的地)限制的原因 - 它们必须简短,没有好的代码格式化等.本网站上的评论旨在澄清,而不是作为讨论或论坛帖子.