【问题标题】:C#.Net - Threads are grabbing the same files within a loopC#.Net - 线程在循环中抓取相同的文件
【发布时间】:2014-02-19 02:02:48
【问题描述】:

我正在尝试设计一个程序,该程序使用外部 OCR 应用程序来翻转图像,直到其正面朝上。所有图像位置都保存在 files[] 中。

问题是,一次处理一个文件太慢了,无法处理我拥有的数万张图像。我需要启动 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 应用程序的不同实例处理同一个文件时,这会导致崩溃。

有谁知道发生了什么,或者知道我可以采取完全不同的方法吗?

【问题讨论】:

  • 请注意,虽然这是许多其他问题的重复,但它是那些非常难以搜索的主题之一,所以我很乐意多次回答它以使其更容易找到未来:)
  • 哇...我在@JonSkeet 之前回答了一个问题...我现在可以退休了! :)

标签: c# .net multithreading ocr


【解决方案1】:

您遇到了一个叫做访问修改后的闭包的问题。 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();
            }
        }

【讨论】:

    【解决方案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!

    这对你的情况没有多大帮助,因为你每五个项目就加入一次,所以你需要索引,但是如果你没有有那个位并且 如果您使用的是 C# 5,则可以使用:

    foreach (var file in files)
    {
        ThreadStart start = () => flip(file);
        ...
    }
    

    请注意,在 C# 5 之前,这会出现完全相同的问题。

    有关该问题的更多详细信息,请参阅 Eric Lippert 的博文 (part one;part two)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-01
      • 1970-01-01
      • 2012-08-11
      • 2011-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多