这是我的解释
class MainClass
{
public static async Task<String> AsyncMethod(int delay) {
await Task.Delay (TimeSpan.FromSeconds(delay));
return "The method has finished it's execution after waiting for " + delay + " seconds";
}
public static async Task Approach1(int delay)
{
var response = await AsyncMethod (delay); // await just unwraps Task's result
Console.WriteLine (response);
}
public static Task Approach2(int delay)
{
return AsyncMethod(delay).ContinueWith(message => Console.WriteLine(message)); // you could do the same with
}
public static void Main (string[] args)
{
var operation1 = Approach1 (3);
var operation2 = Approach2 (5);
Task.WaitAll (operation1, operation2);
Console.WriteLine("All operations are completed")
}
}
最终两者Approach1
and Approach2
是相同的代码片段。
The async/await
是围绕任务 API 的语法糖。这需要你的async
方法之前将其分成几部分await
, 之后await
。 “之前”部分立即执行。 “之后”部分在以下情况下执行await
操作完成。由于您获得了对任务的引用,因此您可以通过任务 API 跟踪操作的第二部分。
一般来说async
允许将方法调用视为某种长操作,您可以通过任务 API 引用该操作,并等待它完成并继续执行另一段代码。要么通过ContinueWith
通过使用调用await
一般来说是一样的。
Before async
/await
/Task
人们使用回调的概念,但处理错误非常简单,Task
类似于一个概念callback
除了它能够更轻松地处理异常之外。
一般来说,所有这些任务/异步/等待口头禅都接近概念promises
如果您碰巧使用过 jQuery/JavaScript,那么这里有一个类似的概念,这是一个很好的问题,解释了它是如何完成的“jQuery 延迟和承诺 - .then() 与 .done()"
Edit:我刚刚发现 .NET 缺少以下实现then
功能类似于 jQuery/JavaScript 中的功能。
和...之间的不同ContinueWith
and Then
就是它Then
能够组合任务并按顺序执行它们ContinueWith
不是,它只能并行启动任务,但可以通过await 结构轻松实现。这是我更新的代码,包含整个 shebang:
static class Extensions
{
// Implementation to jQuery-like `then` function in .NET
// According to: http://blogs.msdn.com/b/pfxteam/archive/2012/08/15/implementing-then-with-await.aspx
// Further reading: http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx
public static async Task Then(this Task task, Func<Task> continuation)
{
await task;
await continuation();
}
public static async Task<TNewResult> Then<TNewResult>(
this Task task, Func<Task<TNewResult>> continuation)
{
await task;
return await continuation();
}
public static async Task Then<TResult>(
this Task<TResult> task, Func<TResult,Task> continuation)
{
await continuation(await task);
}
public static async Task<TNewResult> Then<TResult, TNewResult>(
this Task<TResult> task, Func<TResult, Task<TNewResult>> continuation)
{
return await continuation(await task);
}
}
class MainClass
{
public static async Task<String> AsyncMethod1(int delay) {
await Task.Delay (TimeSpan.FromSeconds(delay));
return "The method has finished it's execution after waiting for " + delay + " seconds";
}
public static Task<String> AsyncMethod2(int delay)
{
return Task.Delay (TimeSpan.FromSeconds (delay)).ContinueWith ((x) => "The method has finished it's execution after waiting for " + delay + " seconds");
}
public static async Task<String> Approach1(int delay)
{
var response = await AsyncMethod1 (delay); // await just unwraps Task's result
return "Here is the result of AsyncMethod1 operation: '" + response + "'";
}
public static Task<String> Approach2(int delay)
{
return AsyncMethod2(delay).ContinueWith(message => "Here is the result of AsyncMethod2 operation: '" + message.Result + "'");
}
public static void Main (string[] args)
{
// You have long running operations that doesn't block current thread
var operation1 = Approach1 (3); // So as soon as the code hits "await" the method will exit and you will have a "operation1" assigned with a task that finishes as soon as delay is finished
var operation2 = Approach2 (5); // The same way you initiate the second long-running operation. The method also returns as soon as it hits "await"
// You can create chains of operations:
var operation3 = operation1.ContinueWith(operation1Task=>Console.WriteLine("Operation 3 has received the following input from operation 1: '" + operation1Task.Result + "'"));
var operation4 = operation2.ContinueWith(operation2Task=>Console.WriteLine("Operation 4 has received the following input from operation 2: '" + operation2Task.Result + "'"));
var operation5 = Task.WhenAll (operation3, operation4)
.Then(()=>Task.Delay (TimeSpan.FromSeconds (7)))
.ContinueWith((task)=>Console.WriteLine("After operation3 and 4 have finished, I've waited for additional seven seconds, then retuned this message"));
Task.WaitAll (operation1, operation2); // This call will block current thread;
operation3.Wait (); // This call will block current thread;
operation4.Wait (); // This call will block current thread;
operation5.Wait (); // This call will block current thread;
Console.WriteLine ("All operations are completed");
}
}