【问题标题】:C++ Timer, Thread, periodic callsC++ 定时器、线程、周期性调用
【发布时间】:2012-04-13 22:16:04
【问题描述】:

我对线程安全回调有疑问。

void draw_something() { /* draws something */ }

问题是,如何在主应用程序线程中调用draw_something,而不考虑其他代码(所以它会像主线程中的 C# Timer 和 fire 函数一样)?早些时候,我使用 CreateWindow 创建(在主线程中)辅助窗口,该窗口处理来自 SendMessage 的消息(从另一个计时器线程发送):

void MainThreadFunction(){
    CreateThread(0, NULL, GoProc, NULL, NULL, NULL);
}

DWORD WINAPI GoProc(LPVOID lpParam){
    while(1){
        SendMessage(auxiliary_window_hWnd, ADDINATIONAL_MESSAGE, 0, 0);
        Sleep(30);
    }
    return 0;
}

因此,window 的 MessageQueue 处理安全线程调用,但我认为这不是一种非常高效和优雅的方式。我知道有更好的方法(也许是提升?)但我不知道。

【问题讨论】:

    标签: c++ multithreading winapi timer


    【解决方案1】:

    您可以使用 Windows SetTimer 调用来获取定期的 WM_TIMER 消息并完全跳过第二个线程。

    【讨论】:

    • +1 这也将防止 OP 代码具有的时钟偏差。它总是有超过 30 毫秒的间隔。
    • 定时器也可能会出现偏差。对于这个用例来说,这似乎不是问题。
    【解决方案2】:

    您不能只是神奇地“中断”正在运行的线程并“注入”您自己的代码,而不是在用户空间中。

    如果您没有特别严格的时间要求,您已经拥有的解决方案,本质上是message passing 的一种形式。

    如果时间对您很重要,即您必须保证事件(在您的情况下是时间的流逝)和该事件的处理之间存在一定的延迟,您必须在“检测到”事件的线程或维护一个工作线程池准备唤醒并立即进行处理。但我猜draw_something() 必须在 UI 线程上完成,所以这个解决方案可能已经过时了。

    【讨论】:

    • Windows 不太适合硬延迟要求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 2013-05-17
    • 2016-01-05
    • 2011-04-11
    • 1970-01-01
    • 2018-07-25
    相关资源
    最近更新 更多