在 Windows/C++ 上使用多进程应用程序的高精度定时操作



我的主程序创建了多个进程(它们位于子项目生成的不同exe文件中(。

我想做的是在每 40-50 毫秒的主帧内运行每个进程大约 1-2 毫秒。当我使用挂起/恢复线程挂起一个进程(通过挂起它拥有的所有线程,但每个线程只有一个(并恢复下一个时,只有一个开关上下文(挂起旧和恢复新(持续大约 60 毫秒。这甚至更长,甚至是我的主要框架。顺便说一句,我知道不建议以这种方式使用 Sleep,因为唯一的睡眠/唤醒操作持续 15-30 毫秒,我不使用任何操作。

如果我将正在运行的进程的优先级更改为较低,将下一个进程更改为较高;是否可以保证Windows在几微秒内进行上下文切换? 或者我应该考虑什么来实现仅微秒级的敏感过程切换? 我想知道一个简单的挂起/恢复线程操作通常需要多长时间?

目前我不能使用线程代替进程,因为我需要进程的内存隔离,并且我的进程可能会生成和终止自己的线程。像同步方法这样的服务员是否为我提供了高精度的时间?

编辑:建议的同步对象在最大到毫秒的分辨率中(如可等待计时器,多媒体计时器等都以ms的形式获取参数并为您提供ms(。我需要使用QueryPerformanceCounter和其他方法来实现高分辨率,如我所提到的。

正如 Remy 所说,你应该使用同步对象来做到这一点 - 这就是它们的用途。 假设进程 A 首先执行,并希望在某个时候"移交"给进程 B。 然后,它可以执行以下操作:

SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, TRUE };
HANDLE hHandOffToA = CreateEventW (&sa, TRUE, FALSE, L"HandOffToA");
HANDLE hHandOffToB = CreateEventW (&sa, TRUE, FALSE, L"HandOffToB");
// Start process B
CreateProcess (...);
while (!quit)
{
// Do work, and then:
SetEvent (hHandOffToB);
WaitForSingleObject (hHandOffToA, INFINITE);
}
CloseHandle (hHandOffToA);
CloseHandle (hHandOffToB);

然后,进程 B 可以执行以下操作:

HANDLE hHandOffToA = OpenEventW (EVENT_MODIFY_STATE, FALSE, L"HandoffToA");
HANDLE hHandOffToB = OpenEventW (SYNCHRONIZE, FALSE, L"HandoffToB");
while (!quit)    
{
WaitForSingleObject (hHandOffToB, INFINITE);
// Do work, and then:
SetEvent (hHandOffToA);
}
CloseHandle (hHandOffToA);
CloseHandle (hHandOffToB);

当然,您应该包括适当的错误检查,我已将其留给您决定进程 A 应如何告诉进程 B 关闭(我想它可能会杀死它(。 还要记住,事件名称是系统范围的,因此比我更仔细地选择它们。

对于非常高的精度,可以使用以下功能:

void get_clock(LONGLONG* SYSTEM_TIME)
{
static REAL64 multiplier = 1.0;
static BOOL alreadyCalculated = FALSE;
if (alreadyCalculated == FALSE)
{
LARGE_INTEGER frequency;
BOOL result = QueryPerformanceFrequency(&frequency);
if (result == TRUE)
{
multiplier = 1000000000.0 / frequency.QuadPart;
}
else
{
DWORD error = GetLastError();
}
alreadyCalculated = TRUE;
}
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
*SYSTEM_TIME = static_cast<SYSTEM_TIME_TYPE>(time.QuadPart * multiplier);
}

在我的情况下,同步对象不是很合适(但是我在时间不重要的地方使用了它们(,相反,我重新设计了我的逻辑,将占位符放在我的线程需要采取行动的地方,并使用上面的函数计算时间。

但仍然不确定更高优先级的任务是否到达,窗口需要多长时间才能将其带入 CPU 并抢占运行一个。

最新更新