在 parallel.foreach 中使用局部变量
using local variables in parallel.foreach
我真的很难解决这个问题。
该代码应该从文件对话框中导入图像。并且每张图像都应该经过处理并发送到 class 正确。
处理器是一个检测形状的 class,所以基本上我发送每个图像并检测其中的形状(在 class 处理器中过滤到特定标准)
newList 将获取图像中所有形状的中心。
我对并行性知之甚少,我似乎不知道如何解决这个问题。
请记住,我不需要将任何内容从一次迭代传递到另一次迭代。我只是想一次处理和校正图像,整个操作分为线程。
I have every iteration a stand alone one and I need not return anything from one iteration to another.
目前的问题是class正确返回的结果有时不正确。我想这是因为 processor 和 newList 也必须是本地的?如果是,我该如何解决?如果不是我哪里错了?
还要记住,使用普通的 foreach 就可以了
这是我的代码:
Parallel.ForEach(ofd.FileNames,
(file) =>
{
Image exam = Image.FromFile(file);
var cvImage = new Image<Bgr, byte>((Bitmap)exam);
processor = processorMain;
processor.ProcessImage(cvImage);
List<Point> newList = new List<Point>();
newList = processor.getList();
correct.correct(cvImage, answerKey, nOptions);
});
实际的 question/problem 已在评论中说明:
I have every iteration a stand alone one and I need not return anything from one iteration to another.
在这种情况下,您不希望 Image
s 是线程本地的,您只需要它们是本地的。所以解决办法就是简化:
Parallel.ForEach(ofd.FileNames,
(file) =>
{
var cvImage = new Image<Bgr, byte>((Bitmap)exam);
processor = processorMain;
processor.ProcessImage(cvImage);
List<Point> newList = new List<Point>();
newList = processor.getList();
correct.correct(newList, cvImage, answerKey, nOptions);
});
但是您的代码并没有真正在任何地方使用 file
,所以这只是一个粗略的猜测。还不正确。
另一方面,processorMain
、answerKey
和nOptions
的用法是潜在的问题。
再评论几句后,您需要的是:
IList<Image> result = ofd.FileNames
.AsParallel()
.Select( (file) =>
{
Image exam = Image.FromFile(file);
...
return exam;
}).ToList();
您的问题可能出在这几行代码中:
processor = processorMain;
processor.ProcessImage(cvImage);
List<Point> newList = processor.getList(); // don't make a new list and then just throw it away by overwriting it.
看起来 processor
正在处理您的图像并存储一些结果,您稍后可以通过调用 processor.getList()
访问这些结果。但是,如果多个线程 运行 并行,则第二个线程可能会在第一个线程调用它之后但在第一个线程到达 processor.getList()
之前调用 ProcessImage
。这意味着第一个线程将从第二个线程获取列表结果。
最简单的解决方案是在每次迭代中创建一个处理器:
processor = new MyProcessorType();
processor.ProcessImage(cvImage);
List<Point> newList = new List<Point>();
newList = processor.getList();
这取决于处理器不依赖任何静态数据的假设。
另一种选择是修改处理器,以便将点列表存储在线程本地存储中。
我真的很难解决这个问题。
该代码应该从文件对话框中导入图像。并且每张图像都应该经过处理并发送到 class 正确。 处理器是一个检测形状的 class,所以基本上我发送每个图像并检测其中的形状(在 class 处理器中过滤到特定标准)
newList 将获取图像中所有形状的中心。
我对并行性知之甚少,我似乎不知道如何解决这个问题。 请记住,我不需要将任何内容从一次迭代传递到另一次迭代。我只是想一次处理和校正图像,整个操作分为线程。
I have every iteration a stand alone one and I need not return anything from one iteration to another.
目前的问题是class正确返回的结果有时不正确。我想这是因为 processor 和 newList 也必须是本地的?如果是,我该如何解决?如果不是我哪里错了?
还要记住,使用普通的 foreach 就可以了
这是我的代码:
Parallel.ForEach(ofd.FileNames,
(file) =>
{
Image exam = Image.FromFile(file);
var cvImage = new Image<Bgr, byte>((Bitmap)exam);
processor = processorMain;
processor.ProcessImage(cvImage);
List<Point> newList = new List<Point>();
newList = processor.getList();
correct.correct(cvImage, answerKey, nOptions);
});
实际的 question/problem 已在评论中说明:
I have every iteration a stand alone one and I need not return anything from one iteration to another.
在这种情况下,您不希望 Image
s 是线程本地的,您只需要它们是本地的。所以解决办法就是简化:
Parallel.ForEach(ofd.FileNames,
(file) =>
{
var cvImage = new Image<Bgr, byte>((Bitmap)exam);
processor = processorMain;
processor.ProcessImage(cvImage);
List<Point> newList = new List<Point>();
newList = processor.getList();
correct.correct(newList, cvImage, answerKey, nOptions);
});
但是您的代码并没有真正在任何地方使用 file
,所以这只是一个粗略的猜测。还不正确。
另一方面,processorMain
、answerKey
和nOptions
的用法是潜在的问题。
再评论几句后,您需要的是:
IList<Image> result = ofd.FileNames
.AsParallel()
.Select( (file) =>
{
Image exam = Image.FromFile(file);
...
return exam;
}).ToList();
您的问题可能出在这几行代码中:
processor = processorMain;
processor.ProcessImage(cvImage);
List<Point> newList = processor.getList(); // don't make a new list and then just throw it away by overwriting it.
看起来 processor
正在处理您的图像并存储一些结果,您稍后可以通过调用 processor.getList()
访问这些结果。但是,如果多个线程 运行 并行,则第二个线程可能会在第一个线程调用它之后但在第一个线程到达 processor.getList()
之前调用 ProcessImage
。这意味着第一个线程将从第二个线程获取列表结果。
最简单的解决方案是在每次迭代中创建一个处理器:
processor = new MyProcessorType();
processor.ProcessImage(cvImage);
List<Point> newList = new List<Point>();
newList = processor.getList();
这取决于处理器不依赖任何静态数据的假设。
另一种选择是修改处理器,以便将点列表存储在线程本地存储中。