运行 列表中的任务
Running Tasks from List
我正在尝试使用以下方法 运行 任务列表:
List<Task> tasks = new List<Task>();
tasks.Add(new Task(() => this.firstMethod()));
tasks.Add(new Task(() => this.secondMethod()));
但是,如果我使用下面两个示例之一,我会遇到以下问题:
foreach (Task task in tasks)
{
await Task.Run(() => task);
}
在第一种情况下,任务根本 运行。
foreach (Task task in tasks)
{
task.Start();
task.Wait();
}
在第二种情况下,它只 运行 一次,然后我得到以下错误:
Start may not be called on a task that has completed
我错过了什么?
这是一个单元测试,展示了如何做到这一点:
public class TasksTests
{
private readonly ITestOutputHelper _output;
public TasksTests(ITestOutputHelper output)
{
_output = output ?? throw new ArgumentNullException(nameof(output));
}
[Fact]
public async Task CanCreateAndRunTasks()
{
var tasks = new List<Task>
{
new Task(() => _output.WriteLine("Task #1")),
new Task(() => _output.WriteLine("Task #2"))
};
tasks.ForEach(t => t.Start());
await Task.WhenAll(tasks);
}
}
您首先创建任务。然后你需要启动它们。最后,您需要等待所有这些,例如,使用 Task.WhenAll
.
第一个案例样本
foreach (Task task in tasks)
{
await Task.Run(() => task);
}
应该改为
foreach (Task task in tasks)
{
task.Start(); // there is no sense to await since tasks should be run in parallel I suppose
}
第二种情况还不清楚。
你 运行 第一个案例之后的第二个案例吗?如果你在 Start
调用之前刚刚初始化了 tasks
应该没问题,比如
List<Task> tasks = new List<Task>()
{
new Task(() => this.firstMethod()),
new Task(() => this.secondMethod()),
};
foreach (Task task in tasks)
{
task.Start();
task.Wait(); // this causes tasks to be run in sequence (one by one) like with await in the first sample
}
最简单的情况就是使用Task.Run
var tasks = new[Task]
{
Task.Run(firstMethod),
Task.Run(secondMethod),
}; // tasks are started immediately there is no need to start them later
Task.WaitAll(tasks); // wait until all tasks are finished
您不能重复使用任务。那么让我们开始创建一个委托数组
List<Action> tasks = new List<Action>();
tasks.Add(this.firstMethod);
tasks.Add(this.secondMethod);
然后 运行 它们在附加线程上按顺序排列(让主线程自由更新 UI):
foreach (Action task in tasks)
{
await Task.Run(task);
}
但是这个循环可以通过多种方式完成,具体取决于调用代码的上下文和有效负载的性质。
这可能不是最佳解决方案。
我正在尝试使用以下方法 运行 任务列表:
List<Task> tasks = new List<Task>();
tasks.Add(new Task(() => this.firstMethod()));
tasks.Add(new Task(() => this.secondMethod()));
但是,如果我使用下面两个示例之一,我会遇到以下问题:
foreach (Task task in tasks)
{
await Task.Run(() => task);
}
在第一种情况下,任务根本 运行。
foreach (Task task in tasks)
{
task.Start();
task.Wait();
}
在第二种情况下,它只 运行 一次,然后我得到以下错误:
Start may not be called on a task that has completed
我错过了什么?
这是一个单元测试,展示了如何做到这一点:
public class TasksTests
{
private readonly ITestOutputHelper _output;
public TasksTests(ITestOutputHelper output)
{
_output = output ?? throw new ArgumentNullException(nameof(output));
}
[Fact]
public async Task CanCreateAndRunTasks()
{
var tasks = new List<Task>
{
new Task(() => _output.WriteLine("Task #1")),
new Task(() => _output.WriteLine("Task #2"))
};
tasks.ForEach(t => t.Start());
await Task.WhenAll(tasks);
}
}
您首先创建任务。然后你需要启动它们。最后,您需要等待所有这些,例如,使用 Task.WhenAll
.
第一个案例样本
foreach (Task task in tasks)
{
await Task.Run(() => task);
}
应该改为
foreach (Task task in tasks)
{
task.Start(); // there is no sense to await since tasks should be run in parallel I suppose
}
第二种情况还不清楚。
你 运行 第一个案例之后的第二个案例吗?如果你在 Start
调用之前刚刚初始化了 tasks
应该没问题,比如
List<Task> tasks = new List<Task>()
{
new Task(() => this.firstMethod()),
new Task(() => this.secondMethod()),
};
foreach (Task task in tasks)
{
task.Start();
task.Wait(); // this causes tasks to be run in sequence (one by one) like with await in the first sample
}
最简单的情况就是使用Task.Run
var tasks = new[Task]
{
Task.Run(firstMethod),
Task.Run(secondMethod),
}; // tasks are started immediately there is no need to start them later
Task.WaitAll(tasks); // wait until all tasks are finished
您不能重复使用任务。那么让我们开始创建一个委托数组
List<Action> tasks = new List<Action>();
tasks.Add(this.firstMethod);
tasks.Add(this.secondMethod);
然后 运行 它们在附加线程上按顺序排列(让主线程自由更新 UI):
foreach (Action task in tasks)
{
await Task.Run(task);
}
但是这个循环可以通过多种方式完成,具体取决于调用代码的上下文和有效负载的性质。
这可能不是最佳解决方案。