1

我需要实现一个准确一致的延迟或睡眠功能,并且必须能够被取消

这是我的代码:

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 毫秒)时,我们会得到不同的结果。一些电脑显示 10 秒的睡眠持续时间,其他电脑显示 16 秒。

关于 Sleep() 函数的文章说它绑定到窗口中断,并且当持续时间过去时,线程被重新调度(可能不会立即运行)。由于重新调度和中断延迟,上述函数可能会遇到时间错误传播。

Windows 时间戳项目描述了另一种等待计时器对象的技术。我的理解是,这种技术不提供取消的方法(通过另一个主线程)。

问题:
1.如何改进线程延迟或睡眠的实现,可以被另一个任务取消,并且更一致

  1. 可以终止休眠的 AFX 线程吗?
    (当主线程终止休眠的 AFX 线程时会发生什么?)

  2. 当主线程终止调用 WaitForSingleObject 的线程时会发生什么?

精度应该在 10ms 左右,如 10 秒 + 10ms。
结果应该在各种 PC(所有运行 Windows 7 或 10)之间保持一致。

具有正确计时的后台
PC 运行 Windows 7,频率为 2.9 GHz。
计时不正确的 PC 运行的是 3.1 GHz 的 Windows 7,同时运行的任务和应用程序较少。
应用程序是使用 Visual Studio 2017 和 MFC 框架(使用 AFX 进行线程创建)开发的。

4

2 回答 2

0
  • 如何改进线程延迟或睡眠的实现,可以被另一个任务取消,并且更加一致?

  • 可以终止休眠的 AFX 线程吗?(当主线程终止休眠的 AFX 线程时会发生什么?)

    • 我假设您的意思是终止于TerminateThread? AFX 线程只是标准 Windows 线程的包装器。他们没有什么特别或神奇的东西可以区分他们的行为。所以会发生一堆坏事
      • 如果目标线程拥有临界区,该临界区将不会被释放。
      • 如果目标线程正在从堆中分配内存,则不会释放堆锁。
      • 如果目标线程在终止时正在执行某些 kernel32 调用,则线程进程的 kernel32 状态可能不一致。
      • 如果目标线程正在操作共享 DLL 的全局状态,则 DLL 的状态可能会被破坏,从而影响 DLL 的其他用户。
    • 如果您可以访问应用程序的所有源代码,则永远不必这样做。
  • 当主线程终止已调用的线程时会发生什么 WaitForSingleObject

于 2019-05-18T02:41:35.137 回答
0

你根本不应该实施这个。

在 C++11 中,多线程的所有基本必要实用程序都在标准中实现。如果您不使用 C++11 - 然后切换到 C++11 或更高版本 - 在您不能使用的不幸情况下,请使用具有相同功能的Boost 。

基本上,您想要使用此功能执行的操作由std::condition_variable. wait您可以通过使用函数(它接受离开等待所需的条件函数)wait_forwait_until(与总等待时间限制相同wait但具有总等待时间限制)以及唤醒睡眠线程(一个或全部)的方法notify_one将线程置于等待模式notify_all并让他们检查觉醒状况并继续他们的任务。

std::conditional_variable在参考中查看。只需谷歌它,您就会通过示例找到足够的信息。

如果您由于某种原因不信任std::conditional_variable实现,您仍然可以将其用于迷你等待和唤醒。

于 2019-05-17T23:37:07.463 回答