简体   繁体   English

多线程读取随机文件

[英]Multiple threads reading random files

i have a thread pool and all threads have a fixed set of images. 我有一个线程池,所有线程都有一套固定的图像。 Let's say they have each 100 images. 假设他们有100张图片。 I need to detect which image contains another image that reside in an image bank. 我需要检测哪个图像包含驻留在图像库中的另一个图像。

  • thread 1 - 100 images 线程1-100张图片

  • thread 2 - 100 images 线程2-100张图片

  • thread 3 - 100 images 线程3-100张图片

  • thread 4 - 100 images 线程4-100张图片

  • Image Base - 50 images 图片库-50张图片

Now i need all the threads to look inside the Image base to see if one of the images they hold resembles one of the image base. 现在我需要所有的线程来看看图像底座内部,看看图像中的一个,他们持有类似图像基地之一。 I have my image matching done, what i am worried about is if multiple threads might open the same image file. 我有我的图像匹配完成后,我所担心的是,如果多个线程可能会打开相同的图像文件。 What would be the proper way of tackling this ? 解决这个问题的正确方法是什么? It would be nice not to "lock" all the other threads for each IO. 最好不要“锁定”每个IO的所有其他线程。

Thanks ! 谢谢 !

What about something like this, where each thread has a reference to the image bank and provides a delegate that will be called for each of the files in the image bank? 像这样的事情呢,每个线程都有一个对图像库的引用,并提供一个将为图像库中的每个文件调用的委托? Here is a skeleton of what the image bank might look like. 这是图像库看起来的骨架。

public class ImageBank {
    public delegate bool ImageProcessorDelegate(String imageName);

    private readonly List<String> _imageBank;

    public ImageBank() 
    {
        // initialize _imageBank with list of image file names
    }

    private int ImageBankCount {
        get {
            lock(_imageBank) {
                return _imageBank.Count;
            }
        }   
    }

    private List<String> FilterImageBank(ISet<String> exclude) 
    {
        lock(_imageBank)
        {
            return _imageBank.Where(name => !exclude.Contains(name)).ToList();
        }
    }

    public void ProcessImages(ImageProcessorDelegate imageProcessor)
    {
        var continueProcessing = true;
        var processedImages = new HashSet<String>();
        var remainingImages = new List<String>();

        do
        {
            remainingImages = FilterImageBank(processedImages);

            while(continueProcessing && remainingImages.Any())
            {
                var currentImageName = remainingImages[0];
                remainingImages.RemoveAt(0);

                // protect this image being accessed by multiple threads.
                var mutex = new Mutex(false, currentImageName);             
                if (mutex.WaitOne(0))
                {
                    try 
                    {
                        // break out of loop of the processor found what it was looking for.
                        continueProcessing = imageProcessor(currentImageName);
                    }
                    catch (Exception)
                    {
                        // exception thrown by the imageProcessor... do something about it.
                    }
                    finally
                    {
                        // add the current name to the set of images we've alread seen and reset the mutex we acquired
                        processedImages.Add(currentImageName);
                        mutex.ReleaseMutex();
                    }
                }
            }
        }
        while(continueProcessing);
    }
}

Then, each thread would have its list of images ( _myImageList ) and a ThreadProc that looks something like this: 然后,每个线程将有其图像的列表( _myImageList )和ThreadProc ,看起来是这样的:

void ThreadProc(object bank) 
{
  var imageBank = bank as ImageBank;
  foreach(var myImage in _myImageList)
  {
    imageBank.ProcessImages(imageName => 
      {
         // do something with imageName and myImage
         // return true to continue with the next image from the image bank
         // or false to stop processing more images from the image bank
      }
    );
  }
}

Assuming all threads have the same set of images they have to work on, and assuming the pahts to these files are in a list or some other collection, you could try something like this: 假设所有线程都具有必须处理的同一组图像,并假定这些文件的页面位于列表或其他集合中,则可以尝试执行以下操作:

// A shared collection
List<string> paths = new List<string>();
// Fill this collection with your fixed set.

IEnumerator<T> e = paths.GetEnumerator();
// Now create all threads and use e as the parameter. Now all threads have the same enumerator.

// Inside each thread you can do this:
while(true)
{    
    string path;
    lock(e)
    {
        if (!e.MoveNext())
            return; // Exit the thread.
        path = e.Current;
    }
    // From here, open the file, read the image, process it, etc.
}

In this example you only put a lock on the enumerator. 在此示例中,您仅对枚举器加了锁。 Only one thread can read from it at the same time. 同一时间只能读取一个线程。 So each time it is called, a different path will come out of it. 因此,每次调用它时,都会引出一条不同的路径。

Outside the lock you can do all the processing, I/O, etc. 在锁之外,您可以执行所有处理,I / O等。

Of course the collection could also be of another type, like an array. 当然,集合也可以是另一种类型,例如数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM