【C#】51. Await 处理并行任务(WhenAll)以及Task.Delay()

这篇文章主要说明两个问题:1、await如何替代ContinueWith来处理WhenAll之类的并行多任务;2、Task.Delay()的原理。

async static Task GetInfoAsync(string name, int seconds)
{
await Task.Delay(TimeSpan.FromSeconds(seconds));
//await Task.Run(() => Thread.Sleep(TimeSpan.FromSeconds(seconds)));
return string.Format("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
}

async static Task AsynchronousProcessing()
{
Task t1 = GetInfoAsync("Task 1", 3);
Task t2 = GetInfoAsync("Task 2", 5);
string[] results = await Task.WhenAll(t1, t2);
foreach (string result in results)
{
Console.WriteLine(result);
}
}


主线程函数:

Task t = AsynchronousProcessing();
t.Wait();
Console.Read();



任务t1和t2构成的WhenAll任务使用await直接返回结果给string[] results,由于是异步的关系,因此总共等待5秒左右,两个任务都完成。

仔细的话可能会发现,明明是两个线程执行异步操作,为什么线程池线程却用的是同一个?(以下为书中原文)

原因在于Task.Delay在幕后使用了一个计时器,从线程池中获取工作线程,将得带Task.Delay方法返回结果,然后,Task.Delay方法启动计时器并且指定一块代码,该代码会在计时器时间到了Task.Delay方法中指定的时间后被调用。之后立即将工作线程返回到线程池。当计时器时间运行时,我们线程池中任意获取一个可用的工作线程(可能就是运行一个任务时使用的线程)并运行计时器提供给他的代码。

好了,接下来我们来试试其他两种阻塞线程的方法:

1)

await Task.Run(()=> Thread.Sleep(TimeSpan.FromSeconds(seconds)));
这种方法将使得线程(线程池中线程)阻塞指定时间,然后继续执行余下代码。但是请注意,由于是开了两个线程池线程,他们在各自的线程中阻塞,因此运行时间还是5秒钟

2)

Thread.Sleep(TimeSpan.FromSeconds(seconds));
这种方法非常直接,但是却是最糟糕的!因为并没有开线程,而是直接使用了主线程来执行阻塞,由于在阻塞期间不能做任何事情(因为主线程被阻塞,不能要求主线程再去执行其他异步或者非异步操作!),因此实际上这个程序运行了8秒钟


你可能感兴趣的:(c#,await,async,whenall,C#,await,线程池,task)