Il MultiThreading in C in ambiente Windows
https://www.swprog.com/articoli/cmultithreadwin_2.php
Lun 19 Mag 2008





Terminare il Thread

Il thread termina quando termina la relativa thread function, è però possibile fare in modo che il thread termini la sua esecuzione prima di quello che sarebbe il naturale termine della thread function. Per farlo si possono utilizzare due funzioni, la funzione ExitThread, che interrompe l'esecuzione nel thread in cui è invocata, o la funzione TerminateThread, che interrompe il thread il cui handle è quello specificato.
Nel programma seguente il secondo thread viene terminato anticipatamente su richiesta utilizzando la funzione ExitThread. 
thread3.c
  1. #include <windows.h>
  2. #include <stdio.h>
  3.  
  4. HANDLE Thread1, Thread2;
  5. DWORD dwThrdId;
  6. int num = 0;
  7.  
  8. DWORD WINAPI Thread_Method_1(LPVOID param)
  9. {
  10. int i = 0;
  11.  
  12. while (i <= 5)
  13. {
  14. printf("Thread Numero 1\n");
  15. i+=1;
  16. }
  17.  
  18. printf("Thread Numero 1--> Finito\n");
  19. }
  20.  
  21. DWORD WINAPI Thread_Method_2(LPVOID param)
  22. {
  23. int i = 0;
  24.  
  25. while (i <= 10)
  26. {
  27. printf("Thread Numero 2\n");
  28. i+=1;
  29.  
  30. if (i > num)
  31. {
  32. printf("Thread Numero 2 Terminato Anticipatamente\n");
  33. ExitThread(0);
  34. }
  35. }
  36.  
  37. printf("Thread Numero 2--> Finito\n");
  38. ExitThread(0);
  39. }
  40.  
  41. int main(int argc, char* argv[])
  42. {
  43. printf("Inserisci numero cicli: \n");
  44. scanf("%d", &num);
  45.  
  46. Thread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_Method_1, 0,
  47. 0, &dwThrdId);
  48.  
  49. Thread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_Method_2, 0,
  50. 0, &dwThrdId);
  51.  
  52. system("pause");
  53. return 0;
  54. }

Il secondo thread dovrebbe terminare dopo l'esecuzione di dieci cicli della while nella funzione Thread_Method_2, è possibile però chiudere il thread prima dell'esecuzione di questi dieci cicli. Prima della creazione dei thread infatti può essere inserito il numero massimo di cicli della while nella funzione Thread_Method_2, una volta superato il thread viene terminato tramite la funzione ExitThread.

Figura 3.
La funzione ExitThread viene invocata dall'interno stesso della thread function relativa al thread che si vuole terminare.

La funzione ExitThread chiude il thread all'interno del quale viene invocata.

  1. HANDLE WINAPI ExitThread(
  2. __in DWORD dwExitCode
  3. );

dwExitCode indica l'exit code del thread. La funzione non restituisce alcun valore.

Nel programma seguente il secondo thread viene terminato anticipatamente su richiesta utilizzando la funzione TerminateThread.

thread4.c
  1. #include <windows.h>
  2.  
  3. HANDLE Thread1, Thread2;
  4. DWORD dwThrdId;
  5.  
  6. DWORD WINAPI Thread_Method_1(LPVOID param)
  7. {
  8. int i = 0;
  9.  
  10. while (i <= 5)
  11. {
  12. printf("Thread Numero 1\n");
  13. i+=1;
  14. }
  15.  
  16. printf("Thread Numero 1--> Finito\n");
  17. }
  18.  
  19. DWORD WINAPI Thread_Method_2(LPVOID param)
  20. {
  21. int i = 0;
  22.  
  23. while (i <= 10)
  24. {
  25. printf("Thread Numero 2\n");
  26. sleep(1);
  27. i+=1;
  28. }
  29.  
  30. printf("Thread Numero 2--> Finito\n");
  31. }
  32.  
  33. int main(int argc, char* argv[])
  34. {
  35.  
  36. Thread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_Method_1, 0,
  37. 0, &dwThrdId);
  38.  
  39. Thread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_Method_2, 0,
  40. 0, &dwThrdId);
  41.  
  42. sleep(6);
  43. TerminateThread(Thread2, 0);
  44.  
  45. system("pause");
  46. return 0;
  47. }

In questo caso il secondo thread viene terminato, dopo 6 secondi circa dalla sua creazione, con una chiamata alla funzione TerminateThread dall'interno di un altro thread, il thread del processo.


Figura 4.
In questo esempio rispetto a quello precedente il thread viene terminato da una chiamata alla funzione TerminateThread che avviene al di fuori del thread che si vuole terminare.

La funzione TerminateThread chiude il thread il cui handle è quello specificato.

  1. BOOL WINAPI TerminateThread(
  2. __inout HANDLE hThread,
  3. __in DWORD dwExitCode
  4. );

hThread indica il thread da terminare, dwExitCode indica l'exit code del thread.
Se la funzione ha successo restituisce un valore diverso da zero, se non ha successo restituisce zero.

Si ottiene lo stesso risultato se la chiamata alla funzione TerminateThread si trova nell'altro thread creato (o anche nel thread stesso che si vuole terminare) piuttosto che nel thread del main.

thread4_1.c
  1. #include <windows.h>
  2.  
  3. HANDLE Thread1, Thread2;
  4. DWORD dwThrdId;
  5.  
  6. DWORD WINAPI Thread_Method_1(LPVOID param)
  7. {
  8. int i = 0;
  9.  
  10. while (i <= 5)
  11. {
  12. printf("Thread Numero 1\n");
  13. i+=1;
  14. }
  15.  
  16. printf("Thread Numero 1--> Finito\n");
  17.  
  18. sleep(6);
  19. TerminateThread(Thread2, 0);
  20. }
  21.  
  22. DWORD WINAPI Thread_Method_2(LPVOID param)
  23. {
  24. int i = 0;
  25.  
  26. while (i <= 10)
  27. {
  28. printf("Thread Numero 2\n");
  29. sleep(1);
  30. i+=1;
  31. }
  32.  
  33. printf("Thread Numero 2--> Finito\n");
  34. }
  35.  
  36. int main(int argc, char* argv[])
  37. {
  38.  
  39. Thread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_Method_1, 0,
  40. 0, &dwThrdId);
  41.  
  42. Thread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_Method_2, 0,
  43. 0, &dwThrdId);
  44.  
  45. system("pause");
  46. return 0;
  47. }

In questo esempio poco prima del termine del thread 1 viene chiamata la funzione TerminateThread che termina il thread 2.

Figura 5.
In quest'altro esempio il secondo thread viene terminato con una chiamata alla funzione TerminateThread dall'interno del secondo thread stesso se il numero dei cicli della while supera un certo numero precedentemente inserito.

thread4_2.c
  1. #include <windows.h>
  2. #include <stdio.h>
  3.  
  4. HANDLE Thread1, Thread2;
  5. DWORD dwThrdId;
  6. int num = 0;
  7.  
  8. DWORD WINAPI Thread_Method_1(LPVOID param)
  9. {
  10. int i = 0;
  11.  
  12. while (i <= 5)
  13. {
  14. printf("Thread Numero 1\n");
  15. i+=1;
  16. }
  17.  
  18. printf("Thread Numero 1--> Finito\n");
  19. }
  20.  
  21. DWORD WINAPI Thread_Method_2(LPVOID param)
  22. {
  23. int i = 0;
  24.  
  25. while (i <= 10)
  26. {
  27. printf("Thread Numero 2\n");
  28. i+=1;
  29.  
  30. if (i > num)
  31. {
  32. printf("Thread Numero 2 Terminato Anticipatamente\n");
  33. TerminateThread(Thread2, 0);
  34. }
  35. }
  36.  
  37. printf("Thread Numero 2--> Finito\n");
  38. ExitThread(0);
  39. }
  40.  
  41. int main(int argc, char* argv[])
  42. {
  43. printf("Inserisci numero cicli: \n");
  44. scanf("%d", &num);
  45.  
  46. Thread1 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_Method_1, 0,
  47. 0, &dwThrdId);
  48.  
  49. Thread2 = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Thread_Method_2, 0,
  50. 0, &dwThrdId);
  51.  
  52. system("pause");
  53. return 0;
  54. }


Figura 6.
Pagina 2 di 3
Prec 1 2 3 Succ