0

У меня есть обширная задача вычисления изображения, в которой используется около 1 ГБ памяти (один цикл вычислений занимает около 4 секунд). Я обрабатываю эти изображения автоматически, когда они поступают в папку с помощью FileSystemWatcher. Когда FileSystemWatcher запускает событие для нового файла я в очереди на работу в методе EventHandler с:C# ThreadPool, используя меньше потоков, чем ядра из-за ограничений памяти с FileSystemWatcher

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

Моя проблема заключается в том, что программа падает на регулярной основе, когда файлы прибывают быстро. В окне отладки я вижу, что в этот момент используется около 3 ГБ памяти. Когда я использую меньшие изображения, чтобы использовать меньше памяти, никаких сбоев пока нет.

Вопрос: Что я могу сделать, чтобы использовать меньше (возможно только 2) потоков независимо от ядер моего компьютера?

Или мой подход использования FileSystemWatcher для создания новых файлов в пул потоков, абсолютно глупый? Я ничуть не испытываю ничьей или подобными вещами. Итак, более того: это выглядит поточно?

Большое спасибо заранее и все лучшее

Tim

Для полноты здесь код выполняется нитями (немного упрощена для удобства чтения):

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(); 
} 
+2

Как он падает? С OutOfMemoryException? Если это так, вы можете попробовать скомпилировать его как 64 бит. –

+0

Эй, извините за то, что не было ясно: он разбился без каких-либо исключений. Просто открывается это маленькое окно ... «Программа xzy больше не работает» или что она говорит по-английски (на немецком языке: «xyz funktioniert nicht mehr») – CaptIglu

+0

Ситуация, которую вы описываете, выглядит как необработанное исключение. Если вы поместите try/catch в 'ProcessTheNewImage()', он покажет вам, какой из них. –

ответ

3

Threadpool имеет только очень ограниченную форму управления ресурсами. Он будет продолжать добавлять потоки, когда очередь заполняется. Он предназначен для относительно небольших (< 500 мс) заданий. Для предотвращения засорения вашего приложения нет предохранительного клапана.

Для этого можно создать рабочий процесс: событие watcher запускает простые сопоставления данных в ConcurrentQueue, а затем вы создаете 2 или более потока (лучше: задачи) для обработки очереди. Это позволит вам настроить количество потоков.

+0

Спасибо большое! Хорошо это сейчас! Я прочитал, что ThreadPool предназначен для «коротких» заданий, но я отстаю на 4 секунды :)! Я попробую его с 2 или 3 задачами, которые смотрят в список или кортеж имен файлов и маркер, если они уже обработаны. Или есть лучший способ с чередованием очереди? Какая быстрая параллельная очередь? – CaptIglu

+0

'System.Collections.Concurrent.ConcurrentQueue' или, возможно, использовать BlockingCollection (обертка Producer/Consumer вокруг этой очереди) –

+0

Спасибо большое! Теперь я изменил свой код и, похоже, очень стабилен для двух задач для больших изображений. Используя меньшие изображения, я могу использовать намного больше задач, работающих на том же самом. В основном я использовал множество задач. Длина массива определяет многопоточность для моего кода. Я использую отдельный поток, который постоянно смотрит в «ConcurrentQueue» (который заполняется «FileSystemWatcher») и запускает новую задачу для следующего пути к файлу, когда слот в массиве свободен или задача в массиве завершена. В этот момент обработанный путь к файлу является де-очереди из очереди. – CaptIglu