带取消功能的准确睡眠
Accurate Sleep with cancellation
我需要实现一个准确一致的延迟或休眠功能,并且必须能够被取消。
这是我的代码:
bool cancel_flag(false);
void My_Sleep(unsigned int duration)
{
static const size_t SLEEP_INTERVAL = 10U; // 10 milliseconds
while ((!cancel_flag) && (duration > SLEEP_INTERVAL))
{
Sleep(duration);
duration -= SLEEP_INTERVAL;
}
if ((!cancel_flag) && (duration > 0U))
{
Sleep(duration);
}
}
上面的函数是运行在一个工作线程中。主线程能够更改 "cancel_flag" 的值以中止(取消)休眠。
在我的店里,当持续时间为 10 秒(10000 毫秒)时,我们有不同的结果。一些 PC 显示 10 秒的睡眠持续时间,其他 PC 显示 16 秒。
有关 Sleep() 函数的文章说它绑定到 windows 中断,并且当持续时间结束时,将重新安排线程(可能不会立即 运行 )。由于重新安排和中断延迟,上述功能可能会遇到时间错误的传播。
Windows Timestamp Project 描述了另一种等待计时器对象的技术。我的理解是这种技术不提供取消方法(通过另一个主线程)。
问题:
1. 如何改进线程延迟或睡眠的实现,可以被另一个任务取消,并且更一致?
是否可以终止休眠的 AFX 线程?
(当主线程终止休眠的 AFX 线程时会发生什么?)
当主线程终止调用 WaitForSingleObject 的线程时会发生什么?
准确度应该在 10 毫秒左右,如 10 秒 + 10 毫秒。
结果在各种 PC 上应该是一致的(所有 运行ning Windows 7 或 10)。
背景
具有正确时序的 PC 是 运行ning Windows 7,频率为 2.9 GHz。
时序不正确的 PC 为 运行ning Windows 7,频率为 3.1 GHz,同时执行的任务和应用程序较少 运行ning。
应用程序是使用 Visual Studio 2017 和 MFC 框架(使用 AFX 创建线程)开发的。
你根本不应该实施这个。
在 C++11 中,多线程的所有基本必要实用程序都在标准中实现。
如果您不使用 C++11 - 然后切换到 C++11 或更高版本 - 在不幸的情况下您不能,然后使用具有相同功能的 Boost。
基本上,std::condition_variable
涵盖了您想使用此功能执行的操作。您可以使用函数 wait
(它接受离开等待所必需的条件函数)、wait_for
和 wait_until
(与 wait
相同,但具有总等待时间限制)以及 notify_one
和 notify_all
唤醒休眠线程(一个或所有)并让它们检查唤醒条件并继续执行任务的方法。
查看参考资料中的 std::conditional_variable
。只要 google 它,您就会通过示例找到足够的信息。
如果您出于某种原因不信任 std::conditional_variable
实施,您仍然可以将其用于迷你等待和唤醒。
How can I improve my implementation for a thread delay or sleep, that
can be cancelled by another task, and is more consistent?
- 高精度休眠has been discussed here before. I have used a waitable timer approach similar to what's described here.
Can a sleeping AFX thread be terminated? (What happens when a main
thread terminates a sleeping AFX thread?)
- 我假设你的意思是用
TerminateThread
终止? AFX 线程只是标准 Windows 线程的包装器。他们没有什么特别或神奇的东西可以区分他们的行为。所以会发生 bunch of bad stuff:
- 如果目标线程拥有临界区,临界区将不会被释放。
- 如果目标线程正在从堆中分配内存,则不会释放堆锁。
- 如果目标线程在终止时正在执行某些 kernel32 调用,则线程进程的 kernel32 状态可能不一致。
- 如果目标线程正在操纵共享 DLL 的全局状态,则 DLL 的状态可能会被破坏,从而影响 DLL 的其他用户。
- 如果您有权访问应用程序的所有源代码,则永远不必这样做。
What happens when a main thread terminates a thread that has called
WaitForSingleObject
?
- 参见上一条。
CreateEvent
和WaitForSingleObject
实际上是一个recommended way of cleanly terminating threads.
我需要实现一个准确一致的延迟或休眠功能,并且必须能够被取消。
这是我的代码:
bool cancel_flag(false);
void My_Sleep(unsigned int duration)
{
static const size_t SLEEP_INTERVAL = 10U; // 10 milliseconds
while ((!cancel_flag) && (duration > SLEEP_INTERVAL))
{
Sleep(duration);
duration -= SLEEP_INTERVAL;
}
if ((!cancel_flag) && (duration > 0U))
{
Sleep(duration);
}
}
上面的函数是运行在一个工作线程中。主线程能够更改 "cancel_flag" 的值以中止(取消)休眠。
在我的店里,当持续时间为 10 秒(10000 毫秒)时,我们有不同的结果。一些 PC 显示 10 秒的睡眠持续时间,其他 PC 显示 16 秒。
有关 Sleep() 函数的文章说它绑定到 windows 中断,并且当持续时间结束时,将重新安排线程(可能不会立即 运行 )。由于重新安排和中断延迟,上述功能可能会遇到时间错误的传播。
Windows Timestamp Project 描述了另一种等待计时器对象的技术。我的理解是这种技术不提供取消方法(通过另一个主线程)。
问题:
1. 如何改进线程延迟或睡眠的实现,可以被另一个任务取消,并且更一致?
是否可以终止休眠的 AFX 线程?
(当主线程终止休眠的 AFX 线程时会发生什么?)当主线程终止调用 WaitForSingleObject 的线程时会发生什么?
准确度应该在 10 毫秒左右,如 10 秒 + 10 毫秒。
结果在各种 PC 上应该是一致的(所有 运行ning Windows 7 或 10)。
背景
具有正确时序的 PC 是 运行ning Windows 7,频率为 2.9 GHz。
时序不正确的 PC 为 运行ning Windows 7,频率为 3.1 GHz,同时执行的任务和应用程序较少 运行ning。
应用程序是使用 Visual Studio 2017 和 MFC 框架(使用 AFX 创建线程)开发的。
你根本不应该实施这个。
在 C++11 中,多线程的所有基本必要实用程序都在标准中实现。 如果您不使用 C++11 - 然后切换到 C++11 或更高版本 - 在不幸的情况下您不能,然后使用具有相同功能的 Boost。
基本上,std::condition_variable
涵盖了您想使用此功能执行的操作。您可以使用函数 wait
(它接受离开等待所必需的条件函数)、wait_for
和 wait_until
(与 wait
相同,但具有总等待时间限制)以及 notify_one
和 notify_all
唤醒休眠线程(一个或所有)并让它们检查唤醒条件并继续执行任务的方法。
查看参考资料中的 std::conditional_variable
。只要 google 它,您就会通过示例找到足够的信息。
如果您出于某种原因不信任 std::conditional_variable
实施,您仍然可以将其用于迷你等待和唤醒。
How can I improve my implementation for a thread delay or sleep, that can be cancelled by another task, and is more consistent?
- 高精度休眠has been discussed here before. I have used a waitable timer approach similar to what's described here.
Can a sleeping AFX thread be terminated? (What happens when a main thread terminates a sleeping AFX thread?)
- 我假设你的意思是用
TerminateThread
终止? AFX 线程只是标准 Windows 线程的包装器。他们没有什么特别或神奇的东西可以区分他们的行为。所以会发生 bunch of bad stuff:- 如果目标线程拥有临界区,临界区将不会被释放。
- 如果目标线程正在从堆中分配内存,则不会释放堆锁。
- 如果目标线程在终止时正在执行某些 kernel32 调用,则线程进程的 kernel32 状态可能不一致。
- 如果目标线程正在操纵共享 DLL 的全局状态,则 DLL 的状态可能会被破坏,从而影响 DLL 的其他用户。
- 如果您有权访问应用程序的所有源代码,则永远不必这样做。
- 我假设你的意思是用
What happens when a main thread terminates a thread that has called
WaitForSingleObject
?- 参见上一条。
CreateEvent
和WaitForSingleObject
实际上是一个recommended way of cleanly terminating threads.
- 参见上一条。