我有一个线程池,所有线程都有一组固定的图像。假设他们有100张图片。我需要检测哪个图像包含驻留在图像库中的另一个图像。多线程读取随机文件
线程1 - 100图像
线程2 - 100图像
线3 - 100图像
螺纹4 - 100图像
图像库 - 50张图片
现在我需要所有线程来查看图像库内部,以查看它们所持有的某个图像是否与图像库相似。我有我的图像匹配完成,我担心的是如果多个线程可能会打开相同的图像文件。解决这个问题的正确方法是什么?不要为每个IO“锁定”所有其他线程。
谢谢!
我有一个线程池,所有线程都有一组固定的图像。假设他们有100张图片。我需要检测哪个图像包含驻留在图像库中的另一个图像。多线程读取随机文件
线程1 - 100图像
线程2 - 100图像
线3 - 100图像
螺纹4 - 100图像
图像库 - 50张图片
现在我需要所有线程来查看图像库内部,以查看它们所持有的某个图像是否与图像库相似。我有我的图像匹配完成,我担心的是如果多个线程可能会打开相同的图像文件。解决这个问题的正确方法是什么?不要为每个IO“锁定”所有其他线程。
谢谢!
假设所有的线程都在同一组,他们必须努力上的图像,并假设pahts这些文件在列表中或某些其他集合,你可以尝试这样的事:
// 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.
}
在这个例子你只能对枚举器加锁。只有一个线程可以同时读取它。所以每次调用时都会有不同的路径。
锁定外,你可以做所有的处理,I/O等
当然藏品中还可以是另一种类型的,像一个数组。
你的假设是正确的。我想我可能已经解释了一些错误。每个图像必须检查底座中的所有图像。我认为你实施它的方式,它只检查一次基地?由于e.MoveNext()将返回一个不同的路径,因此每个线程都必须获取他们拥有的每个图像,然后再检查它们是否是整个基地。 –
所以......要清楚:你需要一个包含50个图像的集合,您需要与4x100图像进行比较。因此总共需要做50x400 = 20,000比较操作。这50个图像是共享的,这100个图像对于每个线程都是唯一的? –
这正是我需要做的。 –
这样的事情呢,每个线程都有一个对图像库的引用,并提供一个代表图像库中每个文件的代理。这是图像库可能看起来像什么的骨架。
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);
}
}
然后,每个线程将有其图像(_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
}
);
}
}
如果阅读这些图像的唯一操作,你不应该有并发问题(假设一旦线程开始处理,没有其他人更改图像) –
您可以使用[Semaphore](http://msdn.microsoft.com/en-us/library/system.threading.semaphore.aspx)限制可以同时访问图像的线程数量。同样,您可以使用[Mutex](http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx)来确保一次只有一个线程可以访问这些图像。 – Icemanind
我不明白。首先你会说:'所有的线程都有一组固定的图像',但后来你告诉我们:'多个线程可能会打开同一个图像文件'......做还是没有固定的图像集? –