Sma*_*acL 6 c++ user-interface mfc multithreading
我有一个基于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 相关函数,例如 close、setText、SetProgress...,因为它们都需要 GUI 处理程序。如果您确实调用这些函数,则错误将是找不到指定的窗口,因为该处理程序不在线程处理程序映射中。
如果您确实需要更改 GUI,则需要将消息发送到该进度条所有者线程。通过PostThreadMessage让该线程自己处理消息(消息处理程序),具体请参考MSDN。
| 归档时间: | 
 | 
| 查看次数: | 3156 次 | 
| 最近记录: |