2012-04-13 3 views
0

Я хочу остановить поток перед выходом основной программы. Правильно ли этот код? (упрощенный пример)Закрыть Thread Before Exit application

HANDLE hThread; 
BOOL live = TRUE; 



DWORD WINAPI Thread (LPVOID lpParam) 
{ 
.. 
while(live); 
.. 
} 



case WM_DESTROY: 
{ 
live=FALSE;  
WaitForSingleObject(hThread, INFINITE); 
} 
+0

Вы хотите остановить его, но вам нужно его остановить? Есть ли соединение с базой данных или внепроцессный сервер, который вам нужно закрыть? Если нет, самый простой способ остановить поток при выходе программы - выйти из программы - все ваши потоки будут остановлены. –

ответ

0

Нет, это неправильно. У вас нет ничего, что гарантирует, что нить когда-либо увидит изменение. Компилятор волен оптимизировать:

DWORD WINAPI Thread (LPVOID lpParam) 
{ 
.. 
while(live); 
.. 
} 

к:

DWORD WINAPI Thread (LPVOID lpParam) 
{ 
.. 
register bool temp=live; 
while(temp); 
.. 
} 

Это, очевидно, не будет работать.

Это правило - never Доступ к переменной в одном потоке, в то время как другой поток может ее модифицировать, если вы не используете какой-либо конкретный механизм для обеспечения безопасной работы. Если вы будете следовать этому правилу, вы останетесь без проблем.

+1

Я бы проголосовал за вас, но я увижу мнения других народов. Я действительно не верю, что компилятор свободен делать это, только на локальной переменной. Можете ли вы, пожалуйста, разместить демонстрацию или статью? –

+0

Почему бы компилятор не смог это сделать? Можете ли вы опубликовать какой-либо строго соответствующий C++ код, который мог бы отличить? Если нет, то компилятор может это сделать. Если какой-то другой стандарт не запрещает его, чего нет. Это самая основная вещь, которую вы должны понимать, когда начинаете писать многопоточный код. –

+0

Аргументы от невежества довольно ... невежественны. –

2

Для того, чтобы обеспечить поток видит изменения, внесенные в live вам нужно сделать livevolatile:

volatile BOOL live = TRUE; 
+0

в качестве дополнительного совета - упакуйте управление всем этим в объект RAII. Для C++ лучше использовать ресурсы, используя такие объекты. –

+2

Обратите внимание, что это трюк, специфичный для Windows. На большинстве платформ поведение 'volatile' в C и C++ по отношению к потокам не указано. –

3

Самым безопасным способом синхронизации потоков используют некоторые из объектов ядра. В вашем случае вы можете создать "прекратить" событие с CreateEvent и ждать его внутри функции нить обратного вызова:

#include <Windows.h> 
#include <iostream> 
using std::cout; 
using std::cerr; 
using std::endl; 

DWORD WINAPI Callback(LPVOID lpVoid) 
{ 
    HANDLE hTerminateEvent = *(reinterpret_cast<HANDLE*>(lpVoid)); 

    bool terminate = false; 

    while(!terminate) 
    { 
     DWORD retVal = WaitForSingleObject(hTerminateEvent, 0); 

     switch(retVal) 
     { 
      case WAIT_OBJECT_0: 
       cout << "Terminate Event signalled" << endl; 
       terminate = true; 
       break; 
      case WAIT_TIMEOUT: 
       cout << "Keep running..." << endl; 
       Sleep(1000); 
       break; 
      case WAIT_FAILED: 
       cerr << "WaitForSingleObject() failed" << endl; 
       terminate = true; 
       break; 
     } 
    } 

    return 0; 
} 

int main() 
{ 
    DWORD threadID = 0; 
    HANDLE hTerminateEvent = CreateEvent(0, FALSE, FALSE, 0); 
    HANDLE hThread = CreateThread(0, 0, Callback, &hTerminateEvent, 0, &threadID); 

    // allow some time to thread to live 
    Sleep(20000); 

    // set terminate event 
    if(!SetEvent(hTerminateEvent)) 
    { 
     cerr << "SetEvent() failed" << endl;   
     return 1; 
    } 

    // wait for thread to terminate 
    DWORD retVal = WaitForSingleObject(hThread, INFINITE); 

    switch(retVal) 
    { 
     case WAIT_OBJECT_0: 
      cout << "Thread terminated" << endl;    
      break; 
     case WAIT_FAILED: 
      cerr << "WaitForSingleObject() failed" << endl;   
      break; 
    } 

    CloseHandle(hThread); 
    CloseHandle(hTerminateEvent); 

    return 0; 
} 

Выход:

Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Keep running... 
Terminate Event signalled 
Thread terminated 
+0

Я использую аналогичный код, но я вызываю 'WaitForSingleObject' с довольно длинной задержкой, например, 5s (' 5000'), регистрирую сообщение о том, что поток зависает, если я получу 'WAIT_TIMEOUT',' WaitForSingleObject' еще несколько, а затем просто выйти и позволить Windows очистить. Использование 'INFINITE' может помешать вашему процессу выйти из системы. – ixe013

Смежные вопросы