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

时间:2009-11-03 17:47:47

标签: c++ multithreading mfc dialog progress-bar

我的应用程序可能需要一段时间才能连接到数据库。这个连接使用单个库函数调用,即我不能在其中放入进度更新并进行回调或类似的操作。

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

让我画一幅画:

CMyApp::       ProgressThread
InitInstance()      .
    |               .
    |               .
    +-Create Dialog-+
    |               |
    |             Animate
 Connect          Progress
    to             Bar
    DB              |
    |               |
    +-Destroy Dlg---+
    |               .
    |               .

这可能吗?如果是,怎么样?

也许整个事情也可以使用计时器。可能会简单得多,但我也无法做到这一点。

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

    1. 在主线程中,我创建了一个带有连接参数的结构,结果标志和thread-running-flag。后者最初设置为true
    2. 我创建一个线程并将该结构作为参数传递。
    3. 我创建了一个在主线程中显示进度条的对话框。
    4. 同样在主线程中,有一个循环在设置thread-running-flag时运行。它会调用CMyDialog::Animate()来调用CProgressCtrl::StepIt(),然后调用Sleep()
    5. 线程执行db-connection代码,并在完成后将running-flag设置为false
    6. 当主线程退出循环时,它可以完全像以前一样处理错误。
    7. 缺点:在窗口上移动鼠标不起作用。它是看不见的。因此,不能使用取消按钮或其他交互式对话元素。然而,我可以忍受这一点。

      由于您喜欢图表,现在的样子如下:

      CMyApp::        WorkerThread
      InitInstance()      .
          |               .
          |               .
      Create Dialog       .
          |               .
          +-Start Thread--+
          |               |
          |             Connect
       Animate            to
       Progress           DB
         Bar              |
          |               |
          +-Thread Ends---+
          |               .
       Destroy Dlg        .
          |               .
      

5 个答案:

答案 0 :(得分:7)

我希望this有关使用进度条创建自己的线程启动画面的文章可能会有所帮助。我在解决MFC消息队列级别的线程锁定问题时编写了它。

答案 1 :(得分:2)

  1. 使用AfxBeginThread创建工作线程。
  2. 在该线程中创建一个CProgressCtrl并调用Create,将对话框作为CProgressCtrl的父级传递,使用选取框样式进行进度控制。
  3. 在Thread中创建一个消息等待循环:

    MSG msg;
    while(GetMessage(& Msg,NULL,0,0))
    {
      的TranslateMessage(安培; MSG);
      DispatchMessage函数(安培; MSG);
    }

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:1)

将成员变量创建为

CProgressCtrl m_progress;

使用进度条ID <{1}}在m_progress的{​​{1}}中添加DDX_Control

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

DoDataExcchange