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】:在用户模式下无法阻止正在终止的线程。
这意味着任何对象(例如CriticalSection
s 和类内部)都可以处于未定义状态。
使用信号(变量、事件)向线程发出信号,并使用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 中的不间断线程部分的主要内容,如果未能解决你的问题,请参考以下文章
UPS(Uninterrupted Power Supply)——不间断电源基础知识(转)
Marquee(跑马灯)横向纵向无空白的不间断连续循环滚动代码