如何安全地关闭其中有无限循环的THREAD

lsr*_*wat 8 c c++ winapi multithreading beginthreadex

我正在使用_beginthreadex函数创建一个线程.我传入的函数地址有一个无限的while循环(while(1)).我有threadidthreadhandle.

我可以使用TerminateThread(threadhandle,1);但它很危险.

安全的方法是使用杀死线程,_endthreadex但它只能在线程内部使用,我想从外部杀死线程.

所以请建议是否有一种安全的方法来使用threadid或从外部安全地关闭,结束或杀死线程threadhandle.

mg3*_*0rg 13

你应该 - 从字面上 - 永远不要使用TerminateThread().我甚至不是在开玩笑.如果从外部终止线程,则其中保留的所有资源都将泄露,内部访问的所有状态变量将具有未确定状态,依此类推.


您的问题的解决方案可能是通知您的线程完成自己.它可以通过线程安全手段(参见InterlockedIncrement()),Windows事件或类似的东西改变的volatile变量来完成.如果您的线程有一个消息循环,您甚至可以通过发送消息来要求它停止.


Lun*_*din 8

正确的方法是使用CreateEvent创建一个事件"kill me",然后在你希望杀死线程时标记这个事件.而不是让你的线程等待while(1),让它等待while(WaitForSingleObject(hevent_killme, 0)).然后你可以简单地让线程回调完成并返回,不需要调用_endthreadex等.

回调函数示例:

static DWORD WINAPI thread_callback (LPVOID param)
{
  ...
  while(WaitForSingleObject(hevent_killme, 0) != WAIT_OBJECT_0)
  {
    // do stuff
  }

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

呼叫者:

HANDLE hevent_killme = CreateEvent(...);
...

void killthread (void)
{
  SetEvent(hevent_killme);
  WaitForSingleObject(hthread_the_thread, INFINITE);
  CloseHandle(hevent_killme);
  CloseHandle(hthread_the_thread);
} 
Run Code Online (Sandbox Code Playgroud)

永远不要使用TerminateThread.

  • 使用bool变量,然后每次在while(1)循环中对其进行测试...? (2认同)

sim*_*urg 7

相反的while(1),你可以使用while(continue_running),在这里continue_runningTrue当线程循环应该运行.如果要停止线程,请将控制线程设置continue_runningFalse.当然,请确保continue_running使用互斥锁正确保护,因为它是一个可以从两个线程修改其值的变量.

  • @ user9000 - 它不是关于布尔值而是编译器优化.如果您的编译器不具备变量的多线程特性,则可能会缓存/复制/多次执行/跳过/等.它出于性能原因. (3认同)
  • 并且记得将'continue_running'声明为volatile,否则优化可能会破坏您的代码.(在Visual Studio或gcc中,在其他IDE中它可能会有所不同.) (2认同)
  • 如果只有一个线程将其设置为非零值,并且另一个线程将其读取,则无论如何,此类变量的线程安全性可能不是问题.volatile以防止不正确的优化确实是一种很好的做法,但我认为大多数编译器现在都没有做出这样的优化假设错误? (2认同)
  • @ mg30rg没错,最好小心谨慎,你可能还想添加volatile会导致它总是从内存中读取,因为这是在单/多线程应用程序中使用volatile的原因之一. (2认同)