Rij*_*ijk 17 .net c# asynchronous async-await c#-5.0
我在http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx?cs-save-lang=1&cs-lang=csharp上阅读有关异步函数调用的内容.
在第一个例子中,他们这样做,我得到:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
string urlContents = await getStringTask;
Run Code Online (Sandbox Code Playgroud)
但他们解释说,如果没有任何工作要做,你可以这样做:
string urlContents = await client.GetStringAsync();
Run Code Online (Sandbox Code Playgroud)
根据我的理解,await
关键字将暂停代码流,直到函数返回.那么这有什么不同:
string urlContents = client.GetString();
Run Code Online (Sandbox Code Playgroud)
?
Adi*_*ter 13
调用await client.GetStringAsync()
产生执行到调用方法,这意味着它不会等待方法完成执行,因此不会阻塞线程.一旦在后台执行完毕,该方法将从停止的位置继续.
如果你只是调用client.GetString()
,线程的执行将不会继续,直到该方法完成执行,这将阻止线程并可能导致UI无响应.
例:
public void MainFunc()
{
InnerFunc();
Console.WriteLine("InnerFunc finished");
}
public void InnerFunc()
{
// This causes InnerFunc to return execution to MainFunc,
// which will display "InnerFunc finished" immediately.
string urlContents = await client.GetStringAsync();
// Do stuff with urlContents
}
public void InnerFunc()
{
// "InnerFunc finished" will only be displayed when InnerFunc returns,
// which may take a while since GetString is a costly call.
string urlContents = client.GetString();
// Do stuff with urlContents
}
Run Code Online (Sandbox Code Playgroud)
据我所知,await关键字将暂停代码流,直到函数返回
嗯,是和否.
client.GetString()
将阻止线程).实际上,它将返回其调用方法.要通过返回其调用方法来理解它的含义,您可以阅读另一个C#编译器魔术 - 该yield return
语句.
迭代器块yield return
将把方法分解为状态机 - yield return
语句之后的代码只有在MoveNext()
枚举器上调用后才会执行.(见这个和这个).
现在,async/await
机制也基于类似的状态机(然而,它比yield return
状态机复杂得多).
为了简化问题,我们考虑一个简单的异步方法:
public async Task MyMethodAsync()
{
// code block 1 - code before await
// await stateement
var r = await SomeAwaitableMethodAsync();
// code block 2 - code after await
}
Run Code Online (Sandbox Code Playgroud)
async
标识符标记方法时,您会告诉编译器将方法分解为状态机,并且您将await
进入此方法.Thread1
,你的代码调用它MyMethodAsync()
.然后code block 1
将在同一个线程上同步运行.SomeAwaitableMethodAsync()
也将同步调用 - 但是假设该方法启动一个新的异步操作并返回一个Task
.await
进入画面的时候.它会将代码流返回给调用者,并且线程Thread1
可以自由运行调用者代码.那么,什么发生在调用方法取决于调用方法是否await
S于MyMethodAsync()
或做别的东西-但重要的是Thread1
不会被阻断.SomeAwaitableMethodAsync()
最终完成,code block 2
被计划运行.async/await
基于任务并行库构建 - 因此,此调度是通过TPL完成的.code block 2
可能无法在同一个线程上进行调度.被察觉,因此,预计在相同的,如果有的话,当被调用.如果没有活动,那么尽管有可能,将会运行一些不同的线程.Thread1
SynchronizationContext
await
SynchronizationContext
code block 2
SynchronizationContext
MyMethodAsync()
SynchronizationContext
code block 2
最后,我会说,既然async/await
是基于编译器创建的状态机,比如yield return
,它分享了一些缺点 - 例如,你不能await
在一个finally
块里面.
我希望这能解决你的疑虑.