由于 FileSystemWatcher 的内存限制,c# ThreadPool 使用的线程少于内核

c# ThreadPool using less threads than cores because of memory restrictions with FileSystemWatcher

我有一个大量的图像计算任务,它使用大约 1GB 的内存(一个计算周期大约需要 4 秒)。当它们到达文件夹时,我使用 FileSystemWatcher 自动处理这些图像。当 FileSystemWatcher 为新文件触发事件时,我将事件处理程序方法中的工作排队:

private void OnNewFileInDir(object source, FileSystemEventArgs evtArgs)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessTheNewImage), evtArgs.FullPath); 
}

我的问题是当文件快速到达时程序经常崩溃。在调试 window 中,我可以看到那一刻使用了近 3GB 的内存。当我使用较小的图像以使用较少的内存时,没有崩溃(到目前为止)。

我的问题:如何使用更少(也许只有 2 个)独立于计算机内核的线程?

或者我使用 FileSystemWatcher 将新文件提示到线程池的方法是否完全愚蠢?我对线程竞赛或类似事情一点经验都没有。 因此,此外:这看起来线程安全吗?

非常感谢,祝一切顺利

蒂姆

为了完整起见,这里是线程执行的代码(为了便于阅读而做了一些简化):

private void ProcessTheNewImage(object threadFilenameInfo)
{
   String filename = (String)threadFilenameInfo;

   // Load the image
   Image currentImage = Image.FromFile(filename);

   //Calculate the image in an external DLL
   Image currentResultImage = ImageProcessing.getResultImage(currentImage);

   //Create the filename with the result infos
   string saveFileName = "blahblah";

   //Save the image
   currentResultImage.Save(saveFileName);

   //dispose the images
   currentImage.Dispose();
   currentResultImage.Dispose();
}

Threadpool 的资源管理形式非常有限。当队列填满时,它会慢慢地继续添加线程。它适用于相对较小(< 500 毫秒)的作业。没有安全阀可以阻止它堵塞您的应用程序。

您可以为此创建一个工作流程:观察者事件将简单的数据包推送到 ConcurrentQueue 中,然后您创建 2 个或更多线程(更好:任务)来处理队列。这将允许您调整线程数。