DimChtz DimChtz - 1 month ago 10
C++ Question

C++ winapi - new thread on button click causes fatal error

Consider the following code:

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;
// ...
}


Everything was great until I realized that when
crossValidate()
was called the whole program was frozen, simply because
crossValidate()
execution takes hours to finish and the window can't receive other messages. I guess what I need is to start a new thread for
crossValidate()
. And that's exactly what I did:

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

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


Now the program was not frozen but I have 2 new problems:

1) When
crossValidate()
finish it's execution, the window displaying ROC Curve simply disappear (see 2 last lines of code inside
crossValidate()
)

2)
crossValidate()
works only the first time. What I mean is that the first time I click the button
crossValidate()
executes (still ROC window disappear), but after it's first execution if I press the button one more time the program crashes with a fatal error.

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

If you assign to a std::thread that has been started, but not joined or detached, your program will end.

The first time, it hasn't been started yet, so that's fine. The second time, there's already a thread there, so your program crashes.

http://en.cppreference.com/w/cpp/thread/thread/~thread

If *this has an associated thread (joinable() == true), std::terminate() is called.