理想情况下,我想要做的是使用非阻塞模式延迟任务,然后等待所有任务完成。我试图添加Task.Delay返回的任务对象,然后使用Task.WaitAll但似乎这没有帮助。我该如何解决这个问题?
class Program
{
public static async void Foo(int num)
{
Console.WriteLine("Thread {0} - Start {1}", Thread.CurrentThread.ManagedThreadId, num);
var newTask = Task.Delay(1000);
TaskList.Add(newTask);
await newTask;
Console.WriteLine("Thread {0} - End {1}", Thread.CurrentThread.ManagedThreadId, num);
}
public static List<Task> TaskList = new List<Task>();
public static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
int idx = i;
TaskList.Add(Task.Factory.StartNew(() => Foo(idx)));
}
Task.WaitAll(TaskList.ToArray());
}
}
答案 0 :(得分:42)
这是你想要实现的目标吗?
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication
{
class Program
{
public static async Task Foo(int num)
{
Console.WriteLine("Thread {0} - Start {1}", Thread.CurrentThread.ManagedThreadId, num);
await Task.Delay(1000);
Console.WriteLine("Thread {0} - End {1}", Thread.CurrentThread.ManagedThreadId, num);
}
public static List<Task> TaskList = new List<Task>();
public static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
int idx = i;
TaskList.Add(Foo(idx));
}
Task.WaitAll(TaskList.ToArray());
Console.WriteLine("Press Enter to exit...");
Console.ReadLine();
}
}
}
输出:
Thread 10 - Start 0 Thread 10 - Start 1 Thread 10 - Start 2 Thread 6 - End 0 Thread 6 - End 2 Thread 6 - End 1 Press Enter to exit...
答案 1 :(得分:20)
需要注意的是,因为Foo是异步的,所以它本身就是一个任务。您的示例包含的任务只是启动Foo
任务,但不要等待它。
换句话说,Task.WaitAll(TaskList.ToArray())
只是等待每个Task.Delay
开始,但它并没有等待所有这些任务完成。
这可能是你想要实现的目标:
class Program
{
public static async Task Foo(int num)
{
Console.WriteLine("Thread {0} - Start {1}", Thread.CurrentThread.ManagedThreadId, num);
var newTask = Task.Delay(1000);
await newTask;
Console.WriteLine("Thread {0} - End {1}", Thread.CurrentThread.ManagedThreadId, num);
}
public static List<Task> TaskList = new List<Task>();
public static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
int idx = i;
Task fooWrappedInTask = Task.Run(() => Foo(idx));
TaskList.Add(fooWrappedInTask);
}
Task.WaitAll(TaskList.ToArray());
Console.WriteLine("Finished waiting for all of the tasks: - Thread {0}", Thread.CurrentThread.ManagedThreadId);
}
}
我已经测试了这个,它产生了你想要的控制台输出。
<小时/> 这里的主要区别是我们正在调用
Task.Run
而不是Task.Factory.StartNew
。
您的Task
可能会返回Task
,甚至可能会返回另一个Task
。您会将此视为任务的“链条”。
Task.Run
返回代表链中最终任务的Task
。当您等待它时,您正在等待完成任务链中的每个链接。
相比之下,Task.Factory.StartNew
返回表示链中第一个链接的任务。在等待之后,您将与链的其余部分一起等待。在Task
返回的内容不是另一个Task
的绝大多数情况下,这样做很好。