async
-await
不会创建任何额外的线程,这是没有意义的,因为一台计算机一次不止做一件事情的唯一方法是
所以如果async
-await
这两者都没有,那么它如何使应用程序响应呢?如果只有一个线程,那么调用AnyMethod意味着在执行其他任何操作之前等待方法完成,而该方法中的方法必须等待结果才能继续执行。
发布于 2018-03-26 14:23:34
在Windows窗体应用程序中处理一个简单的按钮单击事件:
public async void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("before awaiting");
await GetSomethingAsync();
Console.WriteLine("after awaiting");
}
在传统的、非异步的世界中,单击事件处理程序的按钮看起来如下所示:
public void button1_Click(object sender, EventArgs e)
{
Console.WriteLine("before waiting");
DoSomethingThatTakes2Seconds();
Console.WriteLine("after waiting");
}
当单击表单中的按钮时,应用程序将出现冻结约2秒,而我们则等待此方法完成。所发生的是“消息泵”,基本上是一个循环,被阻塞。
这个循环不断地问windows“有人做了什么事情吗,比如移动鼠标,点击了什么东西?”。用户单击了“tton 1”(或Windows中的等效消息类型),最后调用了button1_Click
以上方法。直到这个方法返回,不然这需要2秒时间,在此期间,没有处理任何消息。
大多数处理窗口的事情都是使用消息来完成的,这意味着如果消息循环停止发送消息,哪怕只是一秒钟,用户很快就会注意到它。例如,如果将记事本或任何其他程序移动到自己的程序之上,然后再次离开,则会向程序发送一系列画图信息,指示窗口的哪个区域现在突然又变得可见。
所以,如果在第一个例子中,async/await
不创建新线程,它是如何实现的?
好吧,结果是你的方法被分成了两部分。这是一种宽泛的主题类型,所以我不会详细介绍,但只需说一下方法就可以分为以下两部分:
await
,包括呼吁GetSomethingAsync
await
说明:
code... code... code... await X(); ... code... code... code...
重新排列:
code... code... code... var x = X(); await X; code... code... code...
^ ^ ^ ^
+---- portion 1 -------------------+ +---- portion 2 ------+
基本上,该方法执行如下:
await
GetSomethingAsync
方法,它执行它的操作,并返回未来将完成2秒的事情到目前为止,我们还在最初的按钮调用中。[医]单击,发生在消息循环调用的主线程上。如果导致await
需要很多时间,UI仍然会冻结。在我们的例子中,await
关键字,再加上一些聪明的编译器魔法,基本上是这样的:“好的,你知道吗,我将从这里点击事件处理程序按钮返回。”。当准备完成时,请告诉我,因为我还有一些代码要执行“。await
并继续执行该方法的其余部分。请注意,此代码再次从消息循环中调用,因此如果此代码碰巧执行了一些冗长的操作而不使用async/await
正确地说,它将再次阻塞消息循环。如果GetSomethingAsync
在2秒内完成线程?是的,那么显然有一条新的线索在起作用。然而,这个线程不是。因为这种方法的异步性,是因为该方法的程序员选择了一个线程来实现异步代码。几乎所有异步I/O别使用线程,他们使用不同的东西。async/await
独自不要旋转新线程,但显然“我们等待的东西”可能是使用线程实现的。
在.NET中,有许多东西不一定是独立的,但仍然是异步的:
SomethingSomethingAsync
或BeginSomething
和EndSomething
还有一个IAsyncResult
参与其中。https://stackoverflow.com/questions/-100004306
复制相似问题