Xen*_*ate 39 c# asynchronous async-await
我有这样的方法:
public static async Task SaveAllAsync()
{
foreach (var kvp in configurationFileMap)
{
using (XmlWriter xmlWriter = XmlWriter.Create(kvp.Value, XML_WRITER_SETTINGS))
{
FieldInfo[] allPublicFields =
kvp.Key.GetFields(BindingFlags.Public | BindingFlags.Static);
await xmlWriter.WriteStartDocumentAsync();
foreach (FieldInfo fi in allPublicFields)
{
await xmlWriter.WriteStartElementAsync("some", "text", "here");
}
await xmlWriter.WriteEndDocumentAsync();
}
}
}
Run Code Online (Sandbox Code Playgroud)
但我正在努力追随当有人打电话时会发生什么SaveAllAsync()
.
我认为会发生的是:
SaveAllAsync()
会将控制权返回给该行的调用者await xmlWriter.WriteStartDocumentAsync();
SaveAllAsync()
(或等待任务)时......会发生什么?将SaveAllAsync()
仍然是第一的await坚持到它被调用?因为没有涉及线程,我猜是这样的......Ste*_*ary 46
您可以await
将该async
方法视为"暂停",直到该操作完成.作为一种特殊情况,如果操作已经完成(或非常快),则await
不会"暂停"该方法; 它会立即继续执行.
因此,在这种情况下(假设WriteStartDocumentAsync
尚未完成),await
将暂停方法并将未完成的任务返回给调用者.注意,方法Task
返回的async
表示该方法; 当方法完成时,那就Task
完成了.
最终,WriteStartDocumentAsync
将完成,并将安排该async
方法的其余部分继续运行.在这种情况下,它会执行该方法的下一部分,直到下一次await
,当它被再次停下时,等最终,async
方法将完成,这将完成Task
对被返回来表示方法.
有关更多信息,我在我的博客上有一个async
/ await
介绍.
Eri*_*ert 24
斯蒂芬斯回答当然是正确的.这是考虑它可能有所帮助的另一种方式.
代码块的继续是代码完成后发生的事情.当你遇到await
两件事时.首先,执行中的当前位置成为等待任务的延续.其次,控制离开当前方法并运行其他一些代码.其他代码可能是第一次调用的延续,或者可能是完全不同的东西,比如说是一个事件处理程序.
但是当电话
xmlWriter.WriteStartDocumentAsync()
已经完成时; 怎么了?当前执行是否中断并返回SaveAllAsync()
?
目前尚不清楚你所说的"完成"是什么意思.WriteStartDocumentAsync
可能在I/O完成线程上启动异步写入,并返回Task
表示异步工作的异步写入.等待这项任务做了两件事,就像我说的那样.首先,此任务的继续成为代码的当前位置.其次,控制离开当前方法并运行其他一些代码.在这种情况下,无论调用什么代码SaveAllAsync
都会运行该调用的延续.
现在让我们假设代码 - SaveAllAsync
继续运行的调用者,并且让我们进一步假设您在具有UI线程的应用程序中,如Windows窗体应用程序或WPF应用程序.现在我们有两个线程:UI线程和IO完成线程.UI线程正在运行SaveAllAsync
最终返回的调用者,现在UI线程只是坐在处理Windows消息的循环中以触发事件处理程序.
最终IO完成,IO完成线程向UI线程发送一条注释,说明"您现在可以继续执行此任务".如果UI线程忙,则该消息排队; 最终UI线程到达它并调用continuation.控制在第一次之后恢复await
,然后进入循环.
现在WriteStartElementAsync
被调用.它再次启动一些运行的代码,这取决于IO完成线程上发生的事情(大概是它的工作方式取决于它,但这是一个合理的猜测),它返回一个Task
表示工作,并且UI线程等待任务.同样,执行中的当前位置被注册为该任务的继续,并且控制返回到调用第一个延续的调用者 - 即UI线程的事件处理器.它继续快乐地处理消息,直到有一天IO线程发出信号并且说嘿,你要求的工作是在IO完成线程上完成的,请调用此任务的继续,所以我们再次绕过循环......
合理?