.net 4.0 使用并行任务库时“foreach”失败
下面的代码创建了正确数量的文件,但每个文件都包含第一个列表的内容。有人能看出我做错了什么吗.net 4.0 使用并行任务库时“foreach”失败,.net-4.0,parallel-processing,task-parallel-library,.net 4.0,Parallel Processing,Task Parallel Library,下面的代码创建了正确数量的文件,但每个文件都包含第一个列表的内容。有人能看出我做错了什么吗 private IList<List<string>> GetLists() { // Code omitted for brevity... } private void DoSomethingInParallel() { var lists = GetLists(); var tasks = new List<Task>(); var fact
private IList<List<string>> GetLists()
{
// Code omitted for brevity...
}
private void DoSomethingInParallel()
{
var lists = GetLists();
var tasks = new List<Task>();
var factory = new TaskFactory();
foreach (var list in lists)
{
tasks.Add(factory.StartNew(() =>
{
WriteListToLogFile(list);
}));
}
Task.WaitAll(tasks.ToArray());
}
我不知道为什么你有一个任务列表,你只使用过其中的一个 编辑: factory.StartNew创建并启动系统。线程。任务。任务 大声思考: 所以列表中的每个列表都有一个单独的任务,调用WriteListToLogFile 我想你需要使用
ThreadPool.QueueUserWorkItem
在任务后的代码中。添加
看看这个例子,看看被接受的答案帖子,我自己也遇到了同样的问题。我仍然不知道为什么会发生这种情况,但我能够通过传入一个state对象使它正常工作
foreach (var list in lists)
{
tasks.Add(factory.StartNew((o) =>
{
var l = o as List<string>;
WriteListToLogFile(l);
}, list));
}
很抱歉没有提前回复。我找到了一个解决方案-虽然我不明白为什么它会起作用 原来,我有这个
foreach (var list in lists)
{
tasks.Add(factory.StartNew(() =>
{
WriteListToLogFile(list);
}));
}
将顺序foreach更改为并行foreach解决了此问题
Parallel.ForEach<string>(lists, list =>
tasks.Add(factory.StartNew(() =>
{
WriteListToLogFile(list);
}));
);
原因在于C计算匿名方法的方式,它们不是真正的闭包。这真的与第三方物流无关。下面的代码打印出所有的d。这不是你所期望的
List<Task> tasks = new List<Task>();
List<string> lists = new List<string>();
lists.AddRange(new string[] { "a", "b", "c", "d" });
foreach (var list in lists)
{
tasks.Add(Task.Factory.StartNew(() =>
{
Console.WriteLine(list);
}));
}
原因是创建匿名方法时list的值不是在方法体中计算的值。使用方法执行时列表的值。您可以通过执行以下操作强制对此进行修复:
List<Task> tasks = new List<Task>();
List<string> lists = new List<string>();
lists.AddRange(new string[] { "a", "b", "c", "d" });
foreach (var list in lists)
{
var localList = list;
tasks.Add(Task.Factory.StartNew(() =>
{
Console.WriteLine(localList);
}));
}
您不必显式地将列表值传递给匿名方法
这篇博文更详细地介绍了这一点:
如果您没有正确读取代码,请查看WriteListToLogFile方法。工厂,开始新的。。。为列表集合中的每个项目创建并启动新任务。+1好的,我现在看到我的错误了:谢谢!!var声明让我感到困惑。ThreadPool是执行并行编程的旧方法,没有提供新的并行任务库那么多的反馈和控制。你真的不应该使用parallel.ForEach而不是ForEach。对于像启动任务这样轻量级的事情来说,这将是非常低效的。请参阅我的答案以获得解释。您不应该使用状态对象。见我的答案/解释。