Threadpool queueuserworkitem со многими потоками

Внимание: я не очень хорошо знаком с работой с пулом потоков, что может быть очевидно из следующего кода. У меня сложилось впечатление, что я мог бы поместить много значений в эту очередь, а затем дождаться завершения одного потока, а затем перейти к следующему, и система будет обрабатывать синхронизацию того, сколько потоков будет запущено.

Я пытаюсь использовать ThreadPool::QueueUserWorkItem(waitcallback, num), где значение num повторяется до динамического значения в зависимости от некоторого предыдущего алгоритма. Проблема, с которой я сталкиваюсь, заключается в том, что программа вылетает, когда она становится слишком высокой.

WaitCallback^ wcb = gcnew WaitCallBack(this, &createImage);
for(int i = 0; i < numBlocks; i++)
{
    ThreadPool::QueueUserWorkItem(wcb, i);
}

Я получаю сообщение "Ошибка выполнения! Это приложение запросило у среды выполнения необычный способ завершения работы. Для получения дополнительной информации обратитесь в службу поддержки приложения".

В моем последнем прогоне было numBlocks = 644.


person Gene Parmesan    schedule 26.03.2013    source источник
comment
Ваш код называется терминация(). Обычно это происходит из-за того, что неуправляемый код вызывал исключение C++, которое не было перехвачено. Ничего общего с фрагментом, который вы разместили. Обязательно отлаживайте код с помощью отладчика, работающего в смешанном режиме.   -  person Hans Passant    schedule 26.03.2013
comment
Если это так, это может быть связано с тем, что я выполняю преобразование изображений, до этого я выполнял задачу линейным образом, и я всегда мог предположить, что файл был закрыт, из которого я читаю. Теперь я спрашиваю, возможно ли, что этот тип исключения может быть вызван несколькими потоками, пытающимися открыть один и тот же файл?   -  person Gene Parmesan    schedule 26.03.2013
comment
Конечно, это не может работать. Он также не требует нескольких потоков, вам обязательно нужно улучшить обработку ошибок.   -  person Hans Passant    schedule 26.03.2013
comment
Я просто надеялся, что мне не придется также изменять классы чтения/записи изображений. Но если я должен, я сделаю это.   -  person Gene Parmesan    schedule 26.03.2013


Ответы (1)


Трудно сказать, что вызвало сбой программы. Скорее всего, в одном из потоков было выброшено исключение, что привело к остановке программы. Вам нужно будет определить, где в вашем коде возникло исключение.

Как вы знаете, ThreadPool::QueueUserWorkItem ставит элемент в очередь для обработки пулом потоков. Но может быть несколько потоков, обрабатывающих элементы из этой очереди. Например, у вас может быть 20 потоков пула, 15 из которых обрабатывают рабочие элементы, которые вы поставили в очередь.

Если у вас действительно есть так много элементов для обработки, и вы хотите, чтобы они выполнялись по одному, почему бы просто не поставить в очередь один поток, чтобы выполнять их по одному. Я никогда не работал с управляемым C++, поэтому не буду писать на нем пример. Но, возможно, вы сможете перевести этот код C#:

void ProcessInBackground(object state)
{
    int numBlocks = (int)state;
    for (int i = 0; i < numBlocks; ++i)
    {
        createImage(i);
    }
}

И тогда вы можете вызвать его с помощью:

ThreadPool::QueueUserWorkItem(ProcessInBackground, numBlocks);

Это создает один поток, который будет обрабатывать элементы по порядку.

Я подозреваю, что вы можете довольно легко преобразовать это в управляемый С++.

person Jim Mischel    schedule 26.03.2013
comment
Я поставил их в очередь для запуска по одному, но затем программа заняла 4 дня. Мне нужно разделить процесс, чтобы он не был линейным, а выполнял сразу несколько преобразований (createImage(int)). Я пытаюсь создать и управлять несколькими потоками функции createImage. Я мог бы сделать это вручную, но я думал, что QueueUserWorkItem оптимизировал программу на основе моей машины - person Gene Parmesan; 26.03.2013
comment
@GeneParmesan: вам следует изучить Parallel.ForEach и библиотеку параллельных задач. Они будут лучше распределять потоки, чем вы можете легко сделать с ThreadPool API. - person Jim Mischel; 26.03.2013