Windows API 中的不间断线程部分

Posted

技术标签:

【中文标题】Windows API 中的不间断线程部分【英文标题】:Uninterruptible thread section in Windows API 【发布时间】:2015-09-27 14:19:10 【问题描述】:

我正在 Windows 环境中编写多线程应用程序。 工作循环由 TerminateThread 终止。 我想知道如何实现不能被中断的代码以避免数据丢失/内存问题: 例如(伪代码)

while(true)

#NONINTERRUPTIBLE REGION

do something

#END OF NONINTERRUPTIBLE REGION
#THREAD WILL BE INTERRUPTED THERE (even if call was made earlier)

我在 Windows API 中找不到任何可以帮助执行此操作的函数。 有人可以给我建议如何做到这一点(增强库有这个功能)。

【问题讨论】:

您的程序已经损坏。不应调用 TerminateThread。您正在收获使用该功能的恰到好处。是因为你错误地使用了这个功能,才让你问这个问题。唯一可行的解​​决方案是修复损坏的设计。 【参考方案1】:

在用户模式下无法阻止正在终止的线程。

这意味着任何对象(例如CriticalSections 和类内部)都可以处于未定义状态。

使用信号(变量、事件)向线程发出信号,并使用WaitForSingleObject 来查找线程实际消失的时间。

来自MSDN TerminateThread, TerminateThread 很危险,会破坏内核 32 状态、dll 状态和临界区。

显然你的代码中的指针也可能被破坏。

函数TerminateThread 是最后的手段——可能是为了避免一些更糟糕的行为而预先终止程序。

更新 1

volatile int threadOK; // set to false when thread should complete

Threadfunction() 

  while( threadOK )
  
   #NONINTERRUPTIBLE REGION

   do something

   #END OF NONINTERRUPTIBLE REGION
   #THREAD WILL BE INTERRUPTED THERE (even if call was made earlier)
  

【讨论】:

volatile 还不够。虽然这会阻止编译器优化读取操作,但您还必须使读取-修改-写入操作原子化(例如,通过使用 std::atomic)。 @IInspectable 在TerminateThread面前什么都不够。 @DavidHeffernan:答案是使用volatile 代替 TerminateThread,而不是除此之外。 @Harry 好的,我现在明白了 我不确定这是不是真的。见the description of volatile in the VS2015 documentation。如果您处于 ISO 模式,它明确表示您不能使用volatile 进行跨线程通信。 (我不能说我明白为什么!)如果你使用/volatile:ms,你就可以了。【参考方案2】:

似乎是一个糟糕的设计。我会反过来做,让线程检查一些标志并终止。如果您仍然需要能够杀死没有表现的“失控”线程,那么请执行“公平警告”系统,其中每个线程都有一个要查看的标志,如果已设置,则终止。然后监视这些线程,如果它们在 X 时间后没有自行终止,则执行终止。

确保使用std::atomic 以确保正确写入和跨线程读取标志。

【讨论】:

以上是关于Windows API 中的不间断线程部分的主要内容,如果未能解决你的问题,请参考以下文章

text 光滑的不间断滑动

UPS(Uninterrupted Power Supply)——不间断电源基础知识(转)

Marquee(跑马灯)横向纵向无空白的不间断连续循环滚动代码

浅谈Windows API编程

尝试在 Windows Phone 上显示相机胶卷中的图像时出现跨线程异常

用于 I/O 的最新 Windows 线程池 API 使用情况