MFC OnTimer 事件中 CWinThread 的潜在内存泄漏和性能问题

问题描述 投票:0回答:1

我是一名使用 MFC 的新开发人员,我有一个关于 CWinThread 的问题。我有一个 OnTimer 事件来检查所有轴的位置值是否为 0。此外,我还有一个函数来验证轴位置是否为 0,并且每个轴的此检查可能需要长达 50 秒的时间。总共有11个轴。

目前,我正在使用 CWinThread 函数,该函数运行一个循环,为每个轴创建一个线程。一旦检查了轴的位置,螺纹就会被删除。我在对话框类的构造函数中调用此循环,并且 OnTimer 函数也在同一个对话框类中。

我的问题是:当循环在OnTimer内部执行时,它会执行多次。这会导致内存泄漏或影响应用程序的性能吗?

注意:该场景仅考虑对话框打开时的情况。

for (int i = 0; i < 12; ++i) {
      CheckHomeDone(i);
      Sleep(20);
}


UINT CMotionMovement::CheckHomeDoneThreadTemporary(LPVOID pParam)
{
    MachineSequence* pMachineSequence = reinterpret_cast<MachineSequence*>(pParam);

    pMachineSequence->motionParameters.HomeDone(t_nMotor);

    CWinThread* pThread = AfxGetThread();
    if (pThread != nullptr)  return delete pThread;

    return 0;
}

void CMotionMovement::CheckHomeDone(int motorID)
{
    t_nMotor = motorID;
    CWinThread* pThread = ::AfxBeginThread(CheckHomeDoneThreadTemporary, this, THREAD_PRIORITY_ABOVE_NORMAL);

    if (pThread != nullptr){
          pThread->m_bAutoDelete = FALSE;  
      pThread->ResumeThread();      
    }
    else{
      AfxMessageBox(_T("Failed to create thread"), MB_ICONERROR | MB_OK);
    }
}

//Every 0.5 sec.
void CMotionMovement::OnTimer(UINT_PTR nIDEvent)
{
    if(nIDEvent == MOTION_TIMER && bRunThread) {

        if(!bActiveTimer) {

            bActiveTimer = true;

            RedrawMotorPosStatus();

            if( moveMotorToNextVerificationPosition ) {
            
                moveVerificationMotor();

                linearEncoderPositionCounter = 0;
                verifyLinearEncoderPosition = true;
                displayEncoderVariation = false;

                moveMotorToNextVerificationPosition = false;
            }
            bActiveTimer = false;
        }
    }
    CDialog::OnTimer(nIDEvent);
}

我需要有关如何正确更新详细信息对话框而不导致对话框或应用程序冻结或挂起的建议或解决方案。感谢您的关注。

c++ visual-c++ mfc c++17 thread-safety
1个回答
0
投票

我研究得越多,发现的问题就越多:

  1. 您正在向线程传递对话框对象 (
    this
    ),但在线程过程中您将其强制转换为
    MachineSequence
    。这显然是错误的。您应该传递一个
    MachineSequence
    实例,每个实例都有自己的
    t_nMotor
    成员,如注释中所述(并删除它,是的,从对话框类中删除它)。
  2. 您提到检查最多可能需要 50 秒才能完成。但是,您没有某种机制来阻止或推迟线程运行时的检查。您应该等待所有线程完成,然后再再次检查(创建新线程)。但不知道你的计时器间隔是多少。
  3. CheckHomeDoneThreadTemporary
    (即类成员函数)传递给
    AfxBeginThread()
    是否可以编译?它需要一个免费的函数指针。
  4. 不确定像
    moveVerificationMotor()
    这样的调用是否应该在主线程或工作线程的上下文中执行。如果像
    moveMotorToNextVerificationPosition
    这样的变量可以从工作线程中更改,则需要同步访问。

更一般的注意事项是,您用于检查的技术(称为“轮询”)(即定期检查数据或条件)有很多缺点。只有在不可能的情况下才应使用它。如果您的 API 提供通知,那么应该首选它们。

© www.soinside.com 2019 - 2024. All rights reserved.