MFC中可以有多个GUI线程吗

Can I have multiple GUI threads in MFC?

本文关键字:GUI 线程 MFC      更新时间:2023-10-16

我有一个基于MFC的大型应用程序,它在主线程中包含一些可能非常慢的任务。这可能会使应用程序在实际执行长任务时显示为挂起。从可用性的角度来看,我希望向用户提供更多关于进度的反馈,并可以选择以干净的方式中止任务。虽然将长任务分离到单独的线程中是一个更好的长期解决方案,但我认为一个实用的短期解决方案是创建一个新的GUI线程,该线程封装在自己的对象中,并配有包括进度条和取消按钮在内的对话框,其使用方式与CWait对象类似。主线程通过IsCancelled方法监视取消状态,并在需要时通过throw完成。

这是一种合理的方法吗?如果是的话,是否已经有一些MFC代码可以使用,或者我应该推出自己的代码?第一个草图看起来像这个

class CProgressThread : public CWinThread
{
public:
    CProgressThread(int ProgressMax);      
    ~CProgressThread()
    void SetProgress(int Progress);
    BOOL IsCancelled();
private:
   CProgressDialog  *theDialog;
}
void MySlowTask()
{
   CProgressThread PT(MaxProgress);
   try
   {
       {
           {  // deep in the depths of my slow task
              PT.SetProgress(Progress);
              if (PT.IsCancelled())
                 throw new CUserHasHadEnough; 
           }
        }
    }
    catch (CUserHasHadEnough *pUserHasHadEnough)
    {
        // Clean-up
    }
}    

通常,我倾向于有一个GUI线程和许多工作线程,但这种方法可能会为我节省大量的重构和测试。有什么严重的潜在陷阱吗?

简短回答,是,您可以在MFC中拥有多个GUI线程。但是,除了创建的线程之外,您不能直接访问GUI组件。原因是MFC下的Win32存储基于每个线程的GUI处理程序。这意味着一个线程中的处理程序对另一个线程不可见。如果您跳转到CWinThread类的源代码,您可以在那里找到一个处理程序映射属性。

Windows(MFC)在工作线程&GUI线程。任何线程在创建消息队列后都可以更改为GUI线程,消息队列是在与消息相关的第一次调用(如GetMessage())之后创建的。

在上面的代码中,如果进度条是在一个线程中创建的,而MySlowWork()是在另一个线程调用的。您只能使用CProgressThread属性,而不能触摸Win32 GUI相关功能,如关闭、设置文本、设置进度。。。因为它们都需要GUI处理程序。如果您确实调用了这些函数,错误将是找不到指定的窗口,因为该处理程序不在线程处理程序映射中。

如果确实需要更改GUI,则需要将消息发送到进度条所有者线程。让该线程通过PostThreadMessage自行处理消息(消息处理程序),有关详细信息,请参阅MSDN。