0

我有以下代码:

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 方法中的循环更改为与多个线程并行,我尝试了以下操作,但它不起作用,因为 GetAllTask​​s 返回 IEnumerable 而不是列表

Parallel.ForEach(Task.GetAllTasks(), task =>
{
   //Execute();
});
4

3 回答 3

3

Parallel.ForEach作品IEnumerable<T>,所以调整你GetAllTasks的回报IEnumerable<Task>

.net 也广泛使用 Task 类,我会避免这样命名自己的类以避免混淆。

于 2013-06-06T11:42:17.730 回答
2

Parallel.ForEach需要一个IEnumerable<TSource>,所以你的代码应该没问题。但是,您需要对作为参数传递给 lambda 语句Execute的实例执行调用。task

Parallel.ForEach(Task.GetAllTasks(), task =>
{
    task.Execute();
});

这也可以表示为单行 lambda 表达式:

Parallel.ForEach(Task.GetAllTasks(), task => task.Execute());

您的代码中还有另一个需要注意的细微错误。根据其内部实现,Parallel.ForEach可以并行枚举序列的元素。但是,您正在枚举器中调用Random该类的实例方法,这不是线程安全的,可能会导致竞争问题。解决此问题的最简单方法是将序列预填充为列表:

Parallel.ForEach(Task.GetAllTasks().ToList(), task => task.Execute());

于 2013-06-06T11:36:09.270 回答
0

这适用于我的 linqpad。我刚刚将您的Task课程重命名为Work并返回了IEnumerable<T>from GetAllTasks

class Work
{
        int _delay;
        private Work(int delay) { _delay = delay; }
        public void Execute() { Thread.Sleep(_delay); }
        public static IEnumerable<Work> GetAllTasks()
        {
            Random r = new Random(4711);
            for (int i = 0; i < 10; i++)
                yield return new Work(r.Next(100, 5000));
        }
 }

static class TaskExecuter
{
        public static void Execute()
        {
            foreach (Work task in Work.GetAllTasks())
            {
                 task.Execute();
            }
        }
   }
void Main()
{
    System.Threading.Tasks.Parallel.ForEach(Work.GetAllTasks(), new Action<Work>(task =>
{
   //Execute();
}));
}
于 2013-06-06T11:35:55.577 回答