【问题标题】:Kill a running thread杀死一个正在运行的线程
【发布时间】:2012-05-31 00:47:15
【问题描述】:

如果我们强行杀死一个正在运行的线程会发生什么

我有一个名为RecordThread() 的线程,它调用了一些复杂且耗时的函数。在这些函数中,我使用 try-catch 块、分配和释放内存以及使用临界区变量等。

喜欢

  void RecordThread()
  {
    AddRecord();
    FindRecord();
    DeleteRecord();
    // ...
    ExitThread(0);
   } 

创建此线程后,我会在线程完成执行之前立即将其杀死。在这种情况下,如果线程被强行杀死会发生什么?在我们杀死线程后,内部函数(AddRecordDeleteRecord)是否完成了它们的执行?

【问题讨论】:

    标签: c++ windows multithreading


    【解决方案1】:

    创建此线程后,我会在线程完成执行之前立即将其杀死。

    我假设您的意思是您正在以下列方式使用TerminateThread()

    HANDLE thread = CreateThread(...);
    
    // ...
    // short pause or other action?
    // ...
    
    TerminateThread(thread, 0); // Dangerous source of errors!
    CloseHandle(thread);
    

    如果是这种情况,那么不,执行RecordThread() 的线程将在另一个线程调用TerminateThread() 时完全停止。根据TerminateThread() 文档中的注释,这个确切的点有点随机,取决于您无法控制的复杂时序问题。这意味着您无法在线程内处理正确的清理,因此you should rarely, if ever, kill a thread

    请求线程完成的正确方法是使用WaitForSingleObject(),如下所示:

    HANDLE thread = CreateThread(...);
    
    // ...
    // some other action?
    // ...
    
    // you can pass a short timeout instead and kill the thread if it hasn't
    // completed when the timeout expires.
    WaitForSingleObject(thread, INFINITE);
    CloseHandle(thread);
    

    【讨论】:

    • 更明确地说:TerminateThread 可以在i++ 语句的中间杀死你的线程。它不会尝试寻找诸如函数调用之类的“好”点。
    • 请注意,POSIX 在这方面与 Win32 API 有很大不同(默认情况下,除非线程修改了它的取消设置),它确实只会在取消点杀死你的线程。所以除了危险之外,它甚至在任何地方都不是同样危险的,因此不是“便携的”:-)
    • 如果从其他 cmets 中看不出来,还有一些你不应该使用 TerminateThread 的原因:Windows started picking up the really big pieces of TerminateThread garbage on the sidewalk, but it's still garbage on the sidewalk
    【解决方案2】:

    http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659%28v=vs.85%29.aspx

    ExitThread 是在 C 代码中退出线程的首选方法。但是,在 C++ 代码中,在调用任何析构函数之前退出线程或执行任何其他自动清理。因此,在 C++ 代码中,您应该从您的线程函数中返回。

    但是函数调用当然会完成,因为它们是在 ExitThread() 之前调用的。

    【讨论】:

    • 如果他们没有足够的时间完成怎么办?
    • @sharptooth 就像在单线程代码中一样,顺序一致性保证 ExitThread() 之前的所有行都会完成。
    【解决方案3】:

    杀死线程是最后的手段——正如安德烈所说,它会使数据处于未知状态,如果线程在共享对象上工作,你永远不应该这样做。更好的选择是通过以下方式通知线程完成工作:

    -使用全局volatile(重要)变量,仅由主线程更改并由工作人员测试
    - 使用 signal 类型的同步对象(主要是事件)也由主线程设置并由工作人员测试

    【讨论】:

      【解决方案4】:

      运行良好的线程示例:

      definition in *.h ------------------------------------
      
      DWORD WINAPI Th_EspectroIF(LPVOID lpData);
      
      CThread th_espectro(Th_EspectroIF);
      
      use in *.cc -----------------------------------
      
      DWORD WINAPI Th_EspectroIF(LPVOID lpData)
      {
      
      //Your code...
      
      th_espectro.Stop(true);//stop this Thread 
      
      }
      

      调用线程:th_espectro.Start();

      【讨论】:

      • 欢迎来到 Stack Overflow。不鼓励仅使用代码的答案。这个答案与以前的答案有何不同或更好?
      猜你喜欢
      • 1970-01-01
      • 2018-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多