理解 C# 中的异步/等待
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14177891/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Understanding async / await in C#
提问by Alex Marshall
I'm starting to learn about async / await in C# 5.0, and I don't understand it at all. I don't understand how it can be used for parallelism. I've tried the following very basic program:
我开始学习 C# 5.0 中的 async/await,但我完全不明白。我不明白它如何用于并行性。我尝试了以下非常基本的程序:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Task task1 = Task1();
Task task2 = Task2();
Task.WaitAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await new Task(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
}
}
This program just blocks on the call to Task.WaitAll()
and never finishes, but I am not understanding why. I'm sure I'm just missing something simple or just don't have the right mental model of this, and none of the blogs or MSDN articles that are out there are helping.
这个程序只是阻塞了调用Task.WaitAll()
并且永远不会完成,但我不明白为什么。我敢肯定我只是缺少一些简单的东西,或者只是没有正确的思维模型,而且那里的博客或 MSDN 文章都没有帮助。
采纳答案by Stephen Cleary
I recommend you start out with my intro to async
/await
and follow-up with the official MSDN documentation on TAP.
我建议您从我对async
/ 的介绍await
开始,然后跟进有关 TAP的官方 MSDN 文档。
As I mention in my intro blog post, there are several Task
members that are holdovers from the TPL and have no use in pure async
code. new Task
and Task.Start
should be replaced with Task.Run
(or TaskFactory.StartNew
). Similarly, Thread.Sleep
should be replaced with Task.Delay
.
正如我在介绍性博客文章中提到的,有几个Task
成员是 TPL 的保留成员,在纯async
代码中没有用。new Task
并Task.Start
应替换为Task.Run
(或TaskFactory.StartNew
)。同样,Thread.Sleep
应替换为Task.Delay
。
Finally, I recommend that you do not use Task.WaitAll
; your Console app should just Wait
on a single Task
which uses Task.WhenAll
. With all these changes, your code would look like:
最后,我建议您不要使用Task.WaitAll
; 您的控制台应用程序应该只Wait
在一个Task
使用Task.WhenAll
. 通过所有这些更改,您的代码将如下所示:
class Program
{
static void Main(string[] args)
{
MainAsync().Wait();
}
public static async Task MainAsync()
{
Task task1 = Task1();
Task task2 = Task2();
await Task.WhenAll(task1, task2);
Debug.WriteLine("Finished main method");
}
public static async Task Task1()
{
await Task.Delay(5000);
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(10000);
Debug.WriteLine("Finished Task2");
}
}
回答by MerickOWA
Your tasks never finish because they never start running.
您的任务永远不会完成,因为它们永远不会开始运行。
I would Task.Factory.StartNew
to create a task and start it.
我想Task.Factory.StartNew
创建一个任务并启动它。
public static async Task Task1()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(5)));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Factory.StartNew(() => Thread.Sleep(TimeSpan.FromSeconds(10)));
Debug.WriteLine("Finished Task2");
}
As a side note, if you're really just trying to pause in a async method, there's no need to block an entire thread, just use Task.Delay
作为旁注,如果您真的只是想在异步方法中暂停,则无需阻塞整个线程,只需使用 Task.Delay
public static async Task Task1()
{
await Task.Delay(TimeSpan.FromSeconds(5));
Debug.WriteLine("Finished Task1");
}
public static async Task Task2()
{
await Task.Delay(TimeSpan.FromSeconds(10));
Debug.WriteLine("Finished Task2");
}
回答by Shivprasad Ktheitroadala
Async and await are markers which mark code positions from where control should resume after a task (thread) completes. Here's a detail youtube video which explains the concept in a demonstrative manner http://www.youtube.com/watch?v=V2sMXJnDEjM
Async 和 await 是标记代码位置的标记,它们在任务(线程)完成后应该从哪里恢复控制。这是一个详细的 youtube 视频,它以演示的方式解释了这个概念 http://www.youtube.com/watch?v=V2sMXJnDEjM
If you want you can also read this coodeproject article which explains the same in a more visual manner. http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:-“Async”and“Await”(Codemarkers)
如果您愿意,您还可以阅读这篇 coodeproject 文章,它以更直观的方式解释了相同的内容。 http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1:-“Async”和“Await”(代码标记)
回答by Andrew Zhu
Understand C# Task, async and await
了解 C# 任务、异步和等待
C# Task
C# 任务
Task class is an asynchronous task wrapper. Thread.Sleep(1000) can stop a thread running for 1 second. While Task.Delay(1000) won't stop the current work. See code:
Task 类是一个异步任务包装器。Thread.Sleep(1000) 可以停止一个线程运行 1 秒。而 Task.Delay(1000) 不会停止当前的工作。见代码:
public static void Main(string[] args){
TaskTest();
}
private static void TaskTest(){
Task.Delay(5000);
System.Console.WriteLine("task done");
}
When running," task done" will show up immediately. So I can assume that every method from Task should be asynchronous. If I replace TaskTest () with Task.Run(() =>TaskTest()) task done won't show up at all until I append a Console.ReadLine(); after the Run method.
运行时,会立即显示“任务完成”。所以我可以假设 Task 中的每个方法都应该是异步的。如果我用 Task.Run(() =>TaskTest()) 替换 TaskTest () ,则在我附加 Console.ReadLine() 之前,完成的任务根本不会显示;在 Run 方法之后。
Internally, Task class represent a thread state In a State Machine. Every state in state machine have several states such as Start, Delay, Cancel, and Stop.
在内部,Task 类表示状态机中的线程状态。状态机中的每个状态都有几个状态,例如开始、延迟、取消和停止。
async and await
异步和等待
Now, you may wondering if all Task is asynchronous, what is the purpose of Task.Delay ? next, let's really delay the running thread by using async and await
现在,您可能想知道如果所有 Task 都是异步的,那么 Task.Delay 的目的是什么?接下来,让我们真正通过使用 async 和 await 来延迟正在运行的线程
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
Console.ReadLine();
}
private static async void TaskTest(){
await Task.Delay(5000);
System.Console.WriteLine("task done");
}
async tell caller, I am an asynchronous method, don't wait for me. await inside the TaskTest() ask for waiting for the asynchronous task. Now, after running, program will wait 5 seconds to show the task done text.
async 告诉调用者,我是异步方法,不要等我。在 TaskTest() 中等待请求等待异步任务。现在,运行后,程序将等待 5 秒钟以显示任务完成文本。
Cancel a Task
取消任务
Since Task is a state machine, there must be a way to cancel the task while task is in running.
由于任务是一个状态机,因此必须有一种方法可以在任务运行时取消任务。
static CancellationTokenSource tokenSource = new CancellationTokenSource();
public static void Main(string[] args){
TaskTest();
System.Console.WriteLine("main thread is not blocked");
var input=Console.ReadLine();
if(input=="stop"){
tokenSource.Cancel();
System.Console.WriteLine("task stopped");
}
Console.ReadLine();
}
private static async void TaskTest(){
try{
await Task.Delay(5000,tokenSource.Token);
}catch(TaskCanceledException e){
//cancel task will throw out a exception, just catch it, do nothing.
}
System.Console.WriteLine("task done");
}
Now, when the program is in running, you can input "stop" to cancel the Delay task.
现在,当程序正在运行时,您可以输入“停止”来取消延迟任务。