我开始在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");
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个程序只是阻止呼叫Task.WaitAll(),永远不会完成.有人可以向我解释原因吗?我确信我只是缺少一些简单的东西,或者只是没有正确的心理模型,并且没有任何博客或MSDN文章都有帮助.
Ste*_*ary 63
我建议您先介绍asyncawait我的介绍/并跟进TAP上的官方MSDN文档.
正如我在我的介绍博客文章中提到的,有几个Task成员是TPL的延期,并且在纯async代码中没有用处.new Task并Task.Start应替换为Task.Run(或TaskFactory.StartNew).同样,Thread.Sleep应该替换为Task.Delay.
最后,我建议你不要用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");
}
}
Run Code Online (Sandbox Code Playgroud)
小智 13
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");
}
Run Code Online (Sandbox Code Playgroud)
运行时,"任务完成"将立即显示.所以我可以假设Task中的每个方法都应该是异步的.如果我用Task.Run(()=> TaskTest()替换TaskTest(),那么在我追加一个Console.ReadLine()之前,任务完成都不会显示出来.在Run方法之后.
在内部,Task类表示状态机中的线程状态.状态机中的每个状态都有几个状态,如Start,Delay,Cancel和Stop.
现在,您可能想知道所有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");
}
Run Code Online (Sandbox Code Playgroud)
异步告诉调用者,我是一个异步方法,不要等我.等待TaskTest()内部请求等待异步任务.现在,运行后,程序将等待5秒钟以显示任务完成文本.
由于Task是状态机,因此必须有一种方法可以在任务运行时取消任务.
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");
}
Run Code Online (Sandbox Code Playgroud)
现在,当程序运行时,您可以输入"stop"来取消Delay任务.
Mer*_*OWA 11
你的任务永远不会完成,因为它们从未开始运
我想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");
}
Run Code Online (Sandbox Code Playgroud)
作为旁注,如果你真的只是想在异步方法中暂停,那么就不需要阻塞整个线程,只需使用 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");
}
Run Code Online (Sandbox Code Playgroud)
Async和await是标记代码位置的标记,控制应在任务(线程)完成后从哪里恢复.这是一个详细的YouTube视频,以演示的方式解释了这个概念 http://www.youtube.com/watch?v=V2sMXJnDEjM
如果您愿意,还可以阅读此coodeproject文章,该文章以更直观的方式解释相同内容. http://www.codeproject.com/Articles/599756/Five-Great-NET-Framework-4-5-Features#Feature1: - "异步"和"等待"(代码标记)