Ste*_*pUp 5 c# asynchronous task-parallel-library async-await .net-4.5
我真的好奇async/await如何让你的程序不被停止.我非常喜欢Stephen Cleary如何解释async/await的方式:"我喜欢将"等待"视为"异步等待".也就是说,async方法暂停直到等待完成(所以它等待),但是实际线程没有被阻止(所以它是异步的)."
我已经读过异步方法同步工作,直到compilator满足等待关键字.好.如果compilator无法计算出等待,那么compilator将等待和yield控制排队到调用方法的方法AccessTheWebAsync.好.在调用者(本例中的事件处理程序)内部,处理模式继续.AccessTheWebAsync在等待结果之前,调用者可能会做其他不依赖于结果的工作,或者调用者可能会立即等待.事件处理程序正在等待AccessTheWebAsync,并且AccessTheWebAsync正在等待GetStringAsync.让我们看一个msdn示例:
async Task<int> AccessTheWebAsync()
{
// You need to add a reference to System.Net.Http to declare client.
HttpClient client = new HttpClient();
// GetStringAsync returns a Task<string>. That means that when you await the
// task you'll get a string (urlContents).
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork();
// The await operator suspends AccessTheWebAsync.
// - AccessTheWebAsync can't continue until getStringTask is complete.
// - Meanwhile, control returns to the caller of AccessTheWebAsync.
// - Control resumes here when getStringTask is complete.
// - The await operator then retrieves the string result from getStringTask.
string urlContents = await getStringTask;
// The return statement specifies an integer result.
// Any methods that are awaiting AccessTheWebAsync retrieve the length value.
return urlContents.Length;
}
Run Code Online (Sandbox Code Playgroud)
msdn博客的另一篇文章称,async/await不会创建新线程或使用线程池中的其他线程.好.
我的问题:
async/await在哪里执行等待代码(在我们的示例中下载一个网站)导致控制产生到我们的程序和程序的下一行代码只是询问结果Task<string> getStringTask?我们知道没有新线程,没有使用线程池.
我是否正确地假设CLR只是在一个线程的范围内切换当前可执行代码和方法之间的等待部分?但是更改加数的顺序并不会改变总和,并且可能会在一些不明显的时间内阻止UI.
Ste*_*ary 12
async/await在哪里执行等待代码(在我们的示例中下载一个网站)导致控制产生到我们的程序和程序的下一行代码只是询问Task getStringTask的结果?我们知道没有新线程,没有使用线程池.
如果操作是真正异步的,则没有"执行"代码.您可以将其视为通过回调处理所有内容; HTTP请求被发送(同步)然后HttpClient注册一个将完成的回调Task<string>.下载完成后,将调用回调,完成任务.它比这复杂一点,但这是一般的想法.
我有一篇博文,详细介绍了异步操作如何无线程.
我是否正确地假设CLR只是在一个线程的范围内切换当前可执行代码和方法之间的等待部分?
这是一个部分真实的心理模型,但它不完整.首先,当一个async方法恢复时,它的(前)调用堆栈不会与它一起恢复.所以,async/ await是不是非常不同的纤维或协同例程,即使他们可以用来完成类似的事情.
而不是将其await视为"切换到其他代码",将其视为"返回一个不完整的任务".如果调用方法也调用await,那么它也会返回一个不完整的任务,等等.最后,你要么将一个不完整的任务返回给一个框架(例如,ASP.NET MVC/WebAPI/SignalR,或一个单元测试运行器); 或者你将有一个async void方法(例如,UI事件处理程序).
当操作正在进行时,您最终会得到一个"堆栈"的任务对象.不是真正的堆栈,只是一个依赖树.每个async方法都由一个任务实例表示,它们都在等待异步操作完成.
在哪里继续进行方法的等待部分?
等待任务时,await默认情况下将async在捕获的上下文中恢复其方法.SynchronizationContext.Current除非是这种情况,否则就是null这种情况TaskScheduler.Current.实际上,这意味着async在UI线程上运行的方法将在该UI线程上恢复; async处理ASP.NET请求的方法将继续处理相同的ASP.NET请求(可能在不同的线程上); 在大多数其他情况下,该async方法将在线程池线程上恢复.
在您的问题的示例代码中,GetStringAsync将返回不完整的任务.下载完成后,该任务将完成.因此,当AccessTheWebAsync调用await该下载任务时(假设下载尚未完成),它将捕获其当前上下文,然后从中返回不完整的任务AccessTheWebAsync.
当下载任务完成时,将继续AccessTheWebAsync安排到该上下文(UI线程,ASP.NET请求,线程池......),并且它将Length在该上下文中执行时提取结果.当AccessTheWebAsync方法返回,它集先前从返回的任务的结果AccessTheWebAsync.这反过来将恢复下一个方法等.
| 归档时间: |
|
| 查看次数: |
3306 次 |
| 最近记录: |