我正在尝试设计一个程序,该程序使用外部OCR应用程序将图像翻转直到其正面朝上。所有图像位置都保存在文件[]中。
问题是,一次做一个文件太慢,无法处理我的数万张图像。我需要启动OCR程序的多个实例来同时扫描多个图像。
我糟糕的实现如下:
public Program(string[] files)
{
for(int i = 0; i < files.Length; i++)
{
ThreadStart start = () => {flip(files[i]);};
Thread t = new Thread(start);
t.Start();
if(i % 5 == 0)
{
t.Join();
}
}
}
该代码应该启动5个OCR程序实例。在每五分之一,它等待线程关闭然后继续。这应该充当缓冲区。
然而,正在发生的是重复文件被传递到OCR程序而不是每次迭代的不同文件。不同的线程正在抓取同一个文件。当OCR应用程序的不同实例在同一文件上工作时,这会导致崩溃。
有没有人知道最新情况,或者我知道一种完全不同的做法?
答案 0 :(得分:3)
您遇到了一个名为访问修改后的闭包的问题。 i的值随着线程的开始而变化。更改代码以改为使用局部变量。
for (int i = 0; i < args.Length; i++)
{
int currenti = i;
ThreadStart start = () => { flip(files[currenti]); };
Thread t = new Thread(start);
t.Start();
if (i % 5 == 0)
{
t.Join();
}
}
答案 1 :(得分:2)
问题是你的lambda表达式正在捕获变量 i
,而不是它循环迭代的值。
有两种选择:
抓取副本
for (int i = 0; i < files.Length; i++)
{
int copy = i;
ThreadStart start = () => flip(files[copy]); // Braces aren't needed
...
}
仅使用foreach - C#5!
这对你的情况没有多大帮助,因为你加入了每五个项目,所以你需要索引,但是如果没有那个位和< / em>如果你使用的是C#5,你可以使用:
foreach (var file in files)
{
ThreadStart start = () => flip(file);
...
}
请注意,在C#5之前,这可能会遇到完全相同的问题。