【问题标题】:MFC do while loopMFC做while循环
【发布时间】:2013-07-19 01:53:12
【问题描述】:

我正在做一个测量系统,我的程序中有一个 do while 循环。在循环中,它会在进行测量之前检查是否有任何电机正在移动,因为它需要在执行任何操作之前到达目标位置。

在进行测量时,假设告诉我进行此测量需要多长时间。

但是,每当它在 do while 循环中运行时,我的所有计时器功能都会停止,就好像它们被置于睡眠模式一样。

还有其他方法可以实现吗?如果有,请帮助我。

任何帮助将不胜感激。

SetTimer(TIMERECHO, 1000, NULL);

BOOL bMoving = FALSE;
do
{
    if (IsMoving(ID, NULL, &bMoving)) 
        GetPosition();
} while (bMoving);


void CLHMDlg::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: Add your message handler code here and/or call default
    switch(nIDEvent)
    {
        case TIMERECHO:
            UpdateData(FALSE);
            m_Seconds++;
            m_TimerEcho.Format(_T("Total time: %ds"), m_Seconds);
            break;
    }
    CDialogEx::OnTimer(nIDEvent);
}

【问题讨论】:

    标签: c++ mfc while-loop do-while


    【解决方案1】:

    MFC 有一个消息循环,用于获取和发送 WM_TIMER 等消息。如果您执行 while 循环,则消息循环未运行。它不是在睡觉,它只是在等你停止占用处理器。

    您有两个选择:(1) 摆脱冗长的循环并定期对 WM_TIMER 消息执行任何操作。 (2) 使用第二个线程来执行冗长的操作。这对初学者来说有很多困难。

    【讨论】:

    • 我应该如何编写代码,这样我就不会让 while 循环占用处理器?你能帮我吗?谢谢
    • 使用计时器定期进行测试,而不是循环。每次进行测试时都返回 MFC。这是不占用处理器的方法。
    • 如果你关心你的应用程序使用了多少 CPU,不要坐在一个紧张的循环中检查时间。使用 Windows 中可用的基于回调的计时器之一(请参阅上面我的回复中的链接)
    【解决方案2】:

    这是因为您的循环没有处理消息。 onTimer 作为 Windows 消息的结果被调用。您需要在循环中继续处理消息或使用基于回调的计时器。

    一种方法是使用 CreateTimerQueueTimer http://msdn.microsoft.com/en-us/library/windows/desktop/ms682485%28v=vs.85%29.aspx

    【讨论】:

    • 我该怎么做?抱歉,我是 MFC 编程的初学者。
    • 基于回调的计时器仍然需要一个消息循环 - 回调只是由 DefWindowProc 调用。
    • 不,如果“回调”定时器是旧的 MM 定时器的后代版本之一,则不需要消息循环,例如 msdn.microsoft.com/en-us/library/windows/desktop/…
    【解决方案3】:

    让您跑步的一个非常简单的解决方案(但并不完美)是将您的 IsMoving 移动到计时器,如下所示:

    void CLHMDlg::OnTimer(UINT_PTR nIDEvent)
    {
        // TODO: Add your message handler code here and/or call default
        switch(nIDEvent)
        {
            case TIMERECHO:
               if (IsMoving(ID, NULL, &bMoving)) 
                  GetPosition();
    
                UpdateData(FALSE);
                m_Seconds++;
                m_TimerEcho.Format(_T("Total time: %ds"), m_Seconds);
                break;
        }
        CDialogEx::OnTimer(nIDEvent);
    }
    

    但是,对于正确的解决方案,您必须为此使用线程,其复杂性也会因简单到更好的解决方案而异。我已经为你写了一些代码,它可能无法编译,但你明白了。

    AfxBeginThread(monitor_motor, this);
    
    UINT monitor_motor(LPVOId lParam)
    {
    CMyDlg * dlg = (CMyDlg *) lParam;
    HWND hWnd = (HWND) dlg->m_hWnd;
    
    
    do
    {
        if (IsMoving(ID, NULL, &dlg->bMoving)) 
            GetPosition();
    
        Sleep(100); // maybe you don't have to poll too hard and give other hardware chance to communicate?..that's upto you
    
        PostMessage( hWnd, UPDATE_TIMER_AND_STUFF );
    } while (dlg->bMoving);
    
    PostMessage( hWnd, UPDATE_MOTOR_MOVED_COMPLETELY );
    
    }
    

    【讨论】:

    • 抱歉回复晚了。但是有必要在我的测量中调用这个线程吗?我有一个OnMeasurementStart。我需要在我的按钮中包含线程吗?
    • 是的,这将是最好的方法。我自己实际上也在做类似的事情,关于在这种情况下使用线程的这个主题没有太多资源。
    • 我的意思是,如何将线程调用到我的按钮中? @zadane
    • 不确定你的意思,但是当你按下按钮时使用 AfxBeginThread() 来启动线程
    • 好的,但是我在哪里包括AfxBeginThread(monitor_motor, this); ??在头文件中还是在 CPP 文件中? @zadane
    猜你喜欢
    • 2016-06-08
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 1970-01-01
    • 2020-01-23
    • 2013-12-10
    • 2022-01-06
    相关资源
    最近更新 更多