简体   繁体   English

我可以在MFC中有多个GUI线程吗?

[英]Can I have multiple GUI threads in MFC?

I have a large MFC based application that includes some potentially very slow tasks in the main thread. 我有一个基于MFC的大型应用程序,它包含主线程中一些可能非常慢的任务。 This can give the appearance that the application has hung when it is actually working its way through a long task. 这可以给出应用程序在实际执行长任务时挂起的外观。 From a usability point of view, I'd like to be giving the user some more feedback on progress, and have an option to abort the task in a clean manner. 从可用性的角度来看,我想向用户提供更多关于进度的反馈,并且可以选择以干净的方式中止任务。 While hiving the long tasks off into separate threads would be a better long term solution, I'm thinking a pragmatic short term solution is create a new GUI thread encapsulated in its own object complete with dialog including progress bar and cancel button, used in a similar manner to a CWait object. 虽然将长任务分解为单独的线程将是一个更好的长期解决方案,但我认为一个实用的短期解决方案是创建一个新的GUI线程,封装在自己的对象中,包括进度条和取消按钮,用于与CWait对象类似的方式。 The main thread monitors the cancel status via an IsCancelled method, and finishes via a throw when required. 主线程通过IsCancelled方法监视取消状态,并在需要时通过throw完成。

Is this a reasonable approach, and if so is there some MFC code out there already that I can use, or should I roll my own? 这是一种合理的方法,如果有的话,那里有一些我可以使用的MFC代码,或者我应该自己动手? First sketch looks like this 第一幅草图看起来像这样

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
    }
}    

As a rule, I tend to have one GUI thread and many worker threads, but this approach could possibly save me a bunch of refactoring and testing. 作为一项规则,我倾向于有一个GUI线程和许多工作线程,但这种方法可能会省去一堆重构和测试。 Any serious potential pitfalls? 任何严重的潜在陷阱?

Short answer, Yes, you can have multiple GUI thread in MFC. 简而言之,是的,您可以在MFC中拥有多个GUI线程。 But you can't access the GUI component directly other than the created thread. 但是除了创建的线程之外,您无法直接访问GUI组件。 The reason is because the Win32 under the MFC stores the GUI handler per thread based. 原因是因为MFC下的Win32存储了每个线程的GUI处理程序。 It means the handler in one thread isn't visible to another thread. 这意味着一个线程中的处理程序对另一个线程不可见。 If you jump to the CWinThread class source code, you can find a handler map attribute there. 如果跳转到CWinThread类源代码,可以在那里找到处理程序映射属性。

Windows (MFC) doesn't has hard difference between the worker thread & GUI thread. Windows(MFC)在工作线程和GUI线程之间没有硬性差异。 Any thread can be changed to GUI thread once they create the message queue, which is created after the first call related to the message, such as GetMessage(). 一旦创建了消息队列,就可以将任何线程更改为GUI线程,该消息队列是在与消息相关的第一次调用之后创建的,例如GetMessage()。

In your above code, if the progress bar is created in one thread and MySlowWork() is called in another thread. 在上面的代码中,如果在一个线程中创建了进度条,而在另一个线程中调用了MySlowWork()。 You can only use the CProgressThread attributes without touch the Win32 GUI related functions, such as close, setText, SetProgress... since they all need the GUI handler. 您只能在不触及Win32 GUI相关功能的情况下使用CProgressThread属性,例如close,setText,SetProgress ......因为它们都需要GUI处理程序。 If you do call those function, the error will be can't find the specified window since that handler isn't in the thread handler mapping. 如果您确实调用了这些函数,则错误将无法找到指定的窗口,因为该处理程序不在线程处理程序映射中。

If you do need change the GUI, you need send the message to that progress bar owner thread. 如果确实需要更改GUI,则需要将消息发送到该进度条所有者线程。 Let that thread handles the message by itself (message handler) through the PostThreadMessage, refer to MSDN for detail . 让该线程通过PostThreadMessage自己处理消息(消息处理程序) ,详细信息请参考MSDN

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM