C++ 如何在单独的线程中创建带有进度条的MFC对话框?

C++ 如何在单独的线程中创建带有进度条的MFC对话框?,c++,multithreading,mfc,dialog,progress-bar,C++,Multithreading,Mfc,Dialog,Progress Bar,我的应用程序可能需要一段时间才能连接到数据库。此连接是通过单个库函数调用实现的,也就是说,我不能将进度更新放在其中并进行回调或类似操作 我的想法是在连接到DB之前,在单独的线程中创建一个带有进度条的对话框。此对话框将使用CProgressCtrl::StepIt()不断更改进度状态,以便用户看到发生的事情。 在该对话框设置完成后,我想从主线程调用DB connection函数。 连接函数完成后,我想停止进度条线程 让我画一幅画: CMyApp:: ProgressThread Ini

我的应用程序可能需要一段时间才能连接到数据库。此连接是通过单个库函数调用实现的,也就是说,我不能将进度更新放在其中并进行回调或类似操作

我的想法是在连接到DB之前,在单独的线程中创建一个带有进度条的对话框。此对话框将使用
CProgressCtrl::StepIt()不断更改进度状态,以便用户看到发生的事情。
在该对话框设置完成后,我想从主线程调用DB connection函数。 连接函数完成后,我想停止进度条线程

让我画一幅画:

CMyApp::       ProgressThread
InitInstance()      .
    |               .
    |               .
    +-Create Dialog-+
    |               |
    |             Animate
 Connect          Progress
    to             Bar
    DB              |
    |               |
    +-Destroy Dlg---+
    |               .
    |               .
可能吗?如果是,如何进行

也许整个过程也可以用定时器来完成。可能会简单得多,但我也不能让它工作

  • 我知道
    CProgressCtrl::SetMarquee()
    可能正是我所需要的,但我无法使用它,因为应用程序不支持Unicode
  • 我可以将db连接调用移动到一个单独的线程中,但这样看来,它看起来像是对代码的大量更改和对连接错误的额外处理
  • 更新2
    我按照AlexEzh和Javier De Pedro建议的方式运行:将DB stuf放入自己的线程中。
    起初,我担心如何处理错误,但事实上这与以前的情况非常相似

  • 在主线程中,我创建了一个带有连接参数、结果标志和线程运行标志的结构。后者最初设置为
    true
  • 我创建一个线程并将该结构作为参数传递
  • 我创建了一个在主线程中显示进度条的对话框
  • 在主线程中还有一个循环,该循环在设置线程运行标志时运行。它调用
    CMyDialog::Animate()
    ,调用
    CProgressCtrl::StepIt()
    ,然后调用
    Sleep()
    s一点
  • 线程执行db连接代码,完成后将运行标志设置为
    false
  • 当主线程退出循环时,它可以像以前一样处理错误
  • 缺点:在窗口上移动鼠标不起作用。它是隐形的。因此,不能使用“取消”按钮或其他交互式对话框元素。不过,我可以接受

    既然您喜欢这个图表,下面是它现在的样子:

    CMyApp::        WorkerThread
    InitInstance()      .
        |               .
        |               .
    Create Dialog       .
        |               .
        +-Start Thread--+
        |               |
        |             Connect
     Animate            to
     Progress           DB
       Bar              |
        |               |
        +-Thread Ends---+
        |               .
     Destroy Dlg        .
        |               .
    
    我希望有关使用进度条创建自己的线程启动屏幕的文章能够有所帮助。我是在解决MFC消息队列级别的线程锁定问题时编写的

  • 使用创建工作线程
  • 在该线程中,创建一个and调用,将对话框作为CProgressCtrl的父级传递,并使用字幕样式作为进度控件
  • 在线程中,创建消息等待循环:

    味精
    while(GetMessage(&Msg,NULL,0,0))
    {
    翻译信息(&msg);
    DispatchMessage(&msg);
    }

  • 消息循环需要检查全局标志以查看是否退出循环


  • 将DB连接逻辑移动到单独的线程会更安全。使用对话框线程上的DB,可以重新绘制进度条,但不能重新绘制对话框中的其他控件

    您是否尝试将
    SendMessage
    PBM_SETMARQUEE
    一起使用,而不是
    SETMARQUEE
    。我从来没有试过,但它应该有用

    在我看来,实现您想要做的事情的最简单方法是在ui线程中建立ProgressBar和DB连接,并使用OnTimer在进度条中调用
    StepIt
    。 您还可以在ui线程中创建进度条,并使用工作线程的自定义消息修改进度状态


    无论如何,我同意AlexEzh的观点,最好的方法是让整个非UI在工作线程中工作。

    创建一个成员变量作为

    CProgressCtrl m_progress;
    
    使用进度条ID在
    doDataExchange
    中的
    DDX\U控件中添加
    m\U进度

    在按钮单击功能下添加以下代码

    m_progress.setRange(0,100);
    m_progress.SetPos(1);
    

    您可以在ANSI应用程序中调用SetMarquee(),但这对您没有帮助,因为在我的afxcmn.h中,在主线程上也会调用制作进度条动画的计时器,它看起来是这样的:*如果(WIN32_WINNT>=0x0501)&&defined(UNICODE)\n BOOL SetMarquee(_在BOOL fMarqueeMode中,在int nInterval中)\n#endif/\u WIN32_WINNT>=0x0501&&defined(UNICODE)\n**这就是我无法调用它的原因。在标题中加入一个flock,复制该代码(它只发送一条消息)并使用它。我现在在一个单独的测试项目中进行了尝试:必须满足以下所有条件才能使用字幕:1。在资源属性(PBS_字幕)中启用“字幕”。2.将消息PBM_SETMARQUEE发送到控件。3.使用Unicode支持编译。您可以通过使用模式对话框和计时器来消除此缺点。在OnInit对话框中,启动线程并设置计时器。在OnTimer中,调用StepIt以更新进度。但请确保您控制了所有可能的方法来关闭对话框,以不让用户使用或停止线程。@Kirill这对我来说是可行的,在我的项目中,什么是不可行的?MFC线程可能在Create函数中死锁。为了避免这种情况,您应该使用非MFC线程。@Kirill死锁发生在什么上?两个互相锁定的资源是什么?我可以通过调用RedrawWindow()重新绘制整个对话框。如果我不这样做,只有进度条是动画。这只是非常基本的信息,既没有要求,也没有解决多线程问题。