C winapi — новый поток при нажатии кнопки вызывает фатальную ошибку

#c #multithreading #winapi #fatal-error

#c #многопоточность #winapi #фатальная ошибка

Вопрос:

Рассмотрим следующий код:

 static void crossValidate(HWND hwnd) {
     // Do-stuff (image processing mostly)
     cv::imshow("ROC CURVE", roc);
     cv::waitKey(1);
}

static LRESULT mainOnCommand(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
     int wmId = LOWORD(wParam);
     int wmEvent = HIWORD(wParam);

     switch (wmId) {
          // ...
          case IDMC_CROSSVALID: { crossValidate(hwnd); break; }
          // ...
     }
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
     // ...
     case WM_COMMAND: return mainOnCommand(hwnd, msg, wParam, lParam); break;
     // ...
}
  

Все было замечательно, пока я не понял, что при crossValidate() вызове вся программа была заморожена, просто потому, что crossValidate() выполнение занимает часы, и окно не может получать другие сообщения. Я думаю, что мне нужно запустить новый поток для crossValidate() . И это именно то, что я сделал:

 std::thread crossValidateThread; // global
// ...
// ...

// Inside mainOnCommand()
// ...
case IDMC_CROSSVALID: { crossValidateThread = std::thread(crossValidate,hwnd); break; }
// ...
  

Теперь программа не была заморожена, но у меня есть 2 новые проблемы:

1) По crossValidate() завершении выполнения окно, отображающее кривую ROC, просто исчезает (см. 2 последние строки кода внутри crossValidate() )

2) crossValidate() работает только в первый раз. Я имею в виду, что при первом нажатии кнопки crossValidate() выполняется (окно ROC по-прежнему исчезает), но после первого выполнения, если я нажму кнопку еще раз, программа вылетает с фатальной ошибкой.

Комментарии:

1. если вы запустите свою программу в отладчике, какие результаты вы получите?

2. @xaxxon Ну, я использую vs13, и все, что он делает, это отображает окно с надписью fatal error

3. @Someprogrammerdude Да, это не значит, что он исчезнет. Я имею в виду, когда я не использую поток для вызова crossValidate() , окно не исчезает

Ответ №1:

 crossValidateThread = std::thread(crossValidate,hwnd);
  

Если вы назначаете std::thread, который был запущен, но не присоединен или не отсоединен, ваша программа завершится.

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

http://en.cppreference.com/w/cpp/thread/thread /~ поток

Если * с этим связан поток (joinable() == true), вызывается std::terminate().

Комментарии:

1. @DimChtz Либо это, либо присоединяйтесь к старому, прежде чем создавать новый поток.

2. Это зависит от того, нужно ли вам знать, когда это будет сделано. join () будет блокироваться до тех пор, пока это не будет сделано. Возможно, вам потребуется создать их вектор, если вам нужно хранить N одновременных потоков.

3. Хорошо, это имеет смысл. Что насчет cv::window ? Есть идеи, почему он закрывается?

4. может быть, одна из тех вещей, которые вы делаете после вашего бита // Do-stuff (в основном обработка изображений)? сложно сказать без полного реального кода.

5. «Что насчет cv::window ? Есть идеи, почему он закрывается?» — Я полагаю, потому что он создается в потоке, который не запускает цикл обмена сообщениями и не отправляет сообщения.