我有以下代码:
static void Main(string[] args)
{
TaskExecuter.Execute();
}
class Task
{
int _delay;
private Task(int delay) { _delay = delay; }
public void Execute() { Thread.Sleep(_delay); }
public static IEnumerable GetAllTasks()
{
Random r = new Random(4711);
for (int i = 0; i < 10; i++)
yield return new Task(r.Next(100, 5000));
}
}
static class TaskExecuter
{
public static void Execute()
{
foreach (Task task in Task.GetAllTasks())
{
task.Execute();
}
}
}
我需要将Execute方法中的循环更改为与多个线程并行,我尝试了以下操作,但由于GetAllTasks返回IEnumerable而不是列表,因此无法正常工作
Parallel.ForEach(Task.GetAllTasks(), task =>
{
//Execute();
});
3 回答
Parallel.ForEach
适用于IEnumerable<T>
,因此请调整GetAllTasks
以返回IEnumerable<Task>
.另外.net已广泛使用Task类,我会避免命名自己的类来避免混淆 .
这适用于我的linqpad . 我刚刚将
Task
类重命名为Work
,并从GetAllTasks
返回了IEnumerable<T>
:Parallel.ForEach需要
IEnumerable<TSource>
,因此您的代码应该没问题 . 但是,您需要在作为参数传递给lambda语句的task
实例上执行Execute
调用 .这也可以表示为单行lambda表达式:
您的代码中还有另一个微妙的错误,您应该注意 . 根据其内部实现,Parallel.ForEach可以并行枚举序列的元素 . 但是,您在枚举器中调用Random类的实例方法,该方法不是线程安全的,可能导致种族问题 . 解决此问题的最简单方法是将序列预先填充为列表:
Parallel.ForEach(Task.GetAllTasks() . ToList(),task => task.Execute());