异步/等待
实际上,Async / Await是一对关键字,它们只是用于创建异步任务回调的语法糖。
举个例子:
public static void DoSomeWork()
{
var task = Task.Run(() =>
{
// [RUNS ON WORKER THREAD]
// IS NOT bubbling up due to the different threads
throw new Exception();
Thread.Sleep(2000);
return "Hello";
});
// This is the callback
task.ContinueWith((t) => {
// -> Exception is swallowed silently
Console.WriteLine("Completed");
// [RUNS ON WORKER THREAD]
});
}
上面的代码有几个缺点。错误不会传递,而且很难阅读。
但是Async和Await来帮助我们:
public async static void DoSomeWork()
{
var result = await Task.Run(() =>
{
// [RUNS ON WORKER THREAD]
// IS bubbling up
throw new Exception();
Thread.Sleep(2000);
return "Hello";
});
// every thing below is a callback
// (including the calling methods)
Console.WriteLine("Completed");
}
Await调用必须在Async方法中。这有一些优点:
返回Task的结果
自动创建回调
检查错误并让它们在callstack中冒泡(只适用于callstack中的无等待调用)
等待结果
释放主线程
在主线程上运行回调
使用线程池中的工作线程执行任务
使代码易于阅读
还有更多
注意:Async和Await用于异步调用时不做这些。为此必须使用任务库,如Task. run()。
下面是等待和无等待解决方案之间的比较
这是一个非异步解决方案:
public static long DoTask()
{
stopWatch.Reset();
stopWatch.Start();
// [RUNS ON MAIN THREAD]
var task = Task.Run(() => {
Thread.Sleep(2000);
// [RUNS ON WORKER THREAD]
});
// goes directly further
// WITHOUT waiting until the task is finished
// [RUNS ON MAIN THREAD]
stopWatch.Stop();
// 50 milliseconds
return stopWatch.ElapsedMilliseconds;
}
这是async方法:
public async static Task<long> DoAwaitTask()
{
stopWatch.Reset();
stopWatch.Start();
// [RUNS ON MAIN THREAD]
await Task.Run(() => {
Thread.Sleep(2000);
// [RUNS ON WORKER THREAD]
});
// Waits until task is finished
// [RUNS ON MAIN THREAD]
stopWatch.Stop();
// 2050 milliseconds
return stopWatch.ElapsedMilliseconds;
}
实际上,你可以不使用await关键字而调用async方法,但这意味着这里的任何异常都会在释放模式下被吞噬:
public static Stopwatch stopWatch { get; } = new Stopwatch();
static void Main(string[] args)
{
Console.WriteLine("DoAwaitTask: " + DoAwaitTask().Result + " ms");
// 2050 (2000 more because of the await)
Console.WriteLine("DoTask: " + DoTask() + " ms");
// 50
Console.ReadKey();
}
Async和Await并不用于并行计算。它们用于不阻塞主线程。当涉及asp.net或Windows应用程序时,由于网络调用阻塞主线程是一件糟糕的事情。如果你这样做,你的应用程序将得不到响应,甚至崩溃。
查看微软文档以获得更多的例子。