使用 async 和 await 回调
Callback with async and await
我对异步作业的执行顺序有疑问。
我会用例子问我的问题,因为这样更容易理解。
这是来自 https://msdn.microsoft.com/en-us/library/mt674882.aspx 的官方示例,但有一些改动。
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
//async operation:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoWork1();
// The await operator suspends AccessTheWebAsync.
string urlContents = await getStringTask;
DoWork2();
return urlContents.Length;
}
我可以说 DoWork2
是 client.GetStringAsync
的回调吗?
如果是这样,DoWork2
不会在 client.GetStringAsync
完成后立即执行 IF DoWork1
运行的时间比 client.GetStringAsync
长。
我在这儿吗?
DoWork2
is not immediately executed following the completion of
client.GetStringAsync
if DoWork1
runs longer time than
client.GetStringAsync
一旦你达到那个点 await client.GetStrinkAsync
,DoWork1()
已经完成,从你的例子来看它的执行是同步的。 client.GetStringAsync
完成后,DoWork2
将被设置为执行。
执行流程将是:
GetStringAsync
异步启动。它会一直执行,直到它遇到第一个内部 await
,然后将控制权交还给 AccessTheWebAsync
.
DoWork1()
开始。因为它是同步的,所以每个人都在等待它完成
client.GetStringAsync
是 异步等待 完成。 await
自然会将执行控制权交给它的调用者。
- 一旦
client.GetStringAsync
完成,执行将return到AccessTheWebAsync
,DoWork2()
将同步执行。
urlContents.length
将被 return 编辑。
通常,第一个 await
关键字之后的所有内容都设置为方法其余部分的延续。
在:
//async operation:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
您正在创建一个运行异步操作的任务,returns 立即发送给调用者,接下来 DoWork1()
同步执行,完成后 string urlContents = await getStringTask;
暂停方法的继续,直到等待的任务已经完成;一旦完成,程序将继续 DoWork2()
。
正确。
回答你的后续问题:
Is there a way to make the DoWork2 immediately executed once client.GetStringAsync is finished?
可能吧。这取决于这段代码的上下文。 DoWork1
和 DoWork2
不可能同时在 UI 线程上 运行ning(显然,一个线程一次只能做一件事) .但是,如果这是从线程池上下文中调用的,那么可以肯定的是,可以同时 运行 它们。
但是,您应该将您的想法从"callback" 转变为"operation"。也就是说,不要将其视为 DoWork2
是 GetStringAsync
的 "callback"。相反,可以这样想:我有一个操作 GetStringAsync
,我有一个操作 DoWork2
;我需要一个新的操作,先做一个再做另一个。
一旦你这样转变思路,解决方案就是为新的操作写一个方法:
async Task<string> GetStringAndDoWork2Async()
{
HttpClient client = new HttpClient();
var result = await client.GetStringAsync("http://msdn.microsoft.com");
DoWork2();
return result;
}
现在您可以在更高级别的方法中使用该新操作:
async Task<int> AccessTheWebAsync()
{
var task = GetStringAndDoWork2Async();
DoWork1();
string urlContents = await task;
return urlContents.Length;
}
我对异步作业的执行顺序有疑问。
我会用例子问我的问题,因为这样更容易理解。
这是来自 https://msdn.microsoft.com/en-us/library/mt674882.aspx 的官方示例,但有一些改动。
async Task<int> AccessTheWebAsync()
{
HttpClient client = new HttpClient();
//async operation:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
// You can do work here that doesn't rely on the string from GetStringAsync.
DoWork1();
// The await operator suspends AccessTheWebAsync.
string urlContents = await getStringTask;
DoWork2();
return urlContents.Length;
}
我可以说 DoWork2
是 client.GetStringAsync
的回调吗?
如果是这样,DoWork2
不会在 client.GetStringAsync
完成后立即执行 IF DoWork1
运行的时间比 client.GetStringAsync
长。
我在这儿吗?
DoWork2
is not immediately executed following the completion ofclient.GetStringAsync
ifDoWork1
runs longer time thanclient.GetStringAsync
一旦你达到那个点 await client.GetStrinkAsync
,DoWork1()
已经完成,从你的例子来看它的执行是同步的。 client.GetStringAsync
完成后,DoWork2
将被设置为执行。
执行流程将是:
GetStringAsync
异步启动。它会一直执行,直到它遇到第一个内部await
,然后将控制权交还给AccessTheWebAsync
.DoWork1()
开始。因为它是同步的,所以每个人都在等待它完成client.GetStringAsync
是 异步等待 完成。await
自然会将执行控制权交给它的调用者。- 一旦
client.GetStringAsync
完成,执行将return到AccessTheWebAsync
,DoWork2()
将同步执行。 urlContents.length
将被 return 编辑。
通常,第一个 await
关键字之后的所有内容都设置为方法其余部分的延续。
在:
//async operation:
Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");
您正在创建一个运行异步操作的任务,returns 立即发送给调用者,接下来 DoWork1()
同步执行,完成后 string urlContents = await getStringTask;
暂停方法的继续,直到等待的任务已经完成;一旦完成,程序将继续 DoWork2()
。
回答你的后续问题:
Is there a way to make the DoWork2 immediately executed once client.GetStringAsync is finished?
可能吧。这取决于这段代码的上下文。 DoWork1
和 DoWork2
不可能同时在 UI 线程上 运行ning(显然,一个线程一次只能做一件事) .但是,如果这是从线程池上下文中调用的,那么可以肯定的是,可以同时 运行 它们。
但是,您应该将您的想法从"callback" 转变为"operation"。也就是说,不要将其视为 DoWork2
是 GetStringAsync
的 "callback"。相反,可以这样想:我有一个操作 GetStringAsync
,我有一个操作 DoWork2
;我需要一个新的操作,先做一个再做另一个。
一旦你这样转变思路,解决方案就是为新的操作写一个方法:
async Task<string> GetStringAndDoWork2Async()
{
HttpClient client = new HttpClient();
var result = await client.GetStringAsync("http://msdn.microsoft.com");
DoWork2();
return result;
}
现在您可以在更高级别的方法中使用该新操作:
async Task<int> AccessTheWebAsync()
{
var task = GetStringAndDoWork2Async();
DoWork1();
string urlContents = await task;
return urlContents.Length;
}