MFC中可以有多个GUI线程吗? [英] Can I have multiple GUI threads in MFC?

查看:111
本文介绍了MFC中可以有多个GUI线程吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于MFC的大型应用程序,该应用程序在主线程中包含一些可能非常慢的任务.当应用程序实际上正在通过一个长任务进行工作时,这可以使该应用程序看起来已挂起.从可用性的角度来看,我想向用户提供有关进度的更多反馈,并可以选择以干净的方式中止任务.虽然将长期任务分解为单独的线程将是一个更好的长期解决方案,但我认为一个务实的短期解决方案是创建一个新的GUI线程,将其封装在自己的对象中,并带有对话框(包括进度条和取消按钮),用于与CWait对象类似的方式.主线程通过IsCancelled方法监视取消状态,并在需要时通过抛出来结束.

I have a large MFC based application that includes some potentially very slow tasks in the main thread. 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. The main thread monitors the cancel status via an IsCancelled method, and finishes via a throw when required.

这是一种合理的方法吗?如果可以,那么已经有一些我可以使用的MFC代码了,还是应该自己编写?第一个草图看起来像这样

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

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

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. Any serious potential pitfalls?

推荐答案

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

Short answer, Yes, you can have multiple GUI thread in MFC. But you can't access the GUI component directly other than the created thread. The reason is because the Win32 under the MFC stores the GUI handler per thread based. 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.

Windows(MFC)在工作线程和&线程之间没有硬性区别. GUI线程.创建消息队列后,任何线程都可以更改为GUI线程,该消息队列是在与消息相关的第一次调用之后创建的,例如GetMessage().

Windows (MFC) doesn't has hard difference between the worker thread & GUI thread. 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().

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

In your above code, if the progress bar is created in one thread and MySlowWork() is called in another thread. 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. 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.

如果确实需要更改GUI,则需要将消息发送到该进度栏所有者线程.让该线程自己通过PostThreadMessage处理消息(消息处理程序),

If you do need change the GUI, you need send the message to that progress bar owner thread. Let that thread handles the message by itself (message handler) through the PostThreadMessage, refer to MSDN for detail.

这篇关于MFC中可以有多个GUI线程吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆