繁体   English   中英

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

[英]How to create a MFC dialog with a progress bar in a separate thread?

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

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

让我画一幅画:

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

那可能吗? 如果有,怎么样?

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

  1. 我知道CProgressCtrl::SetMarquee()可能正是我需要的,但我不能使用它因为应用程序没有Unicode支持。
  2. 我可以将数据库连接调用移动到一个单独的线程中,但这样看起来像代码的大量更改和连接错误的额外处理。

更新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代码并在完成false running-flag设置为false
  6. 当主线程退出循环时,它可以完全像以前一样处理错误。

缺点:将鼠标移到窗口上不起作用。 它是看不见的。 因此,不能使用取消按钮或其他交互式对话元素。 但是,我可以忍受这一点。

既然您喜欢这个图表,现​​在的样子如下:

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

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

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

    MSG消息;
    while(GetMessage(&Msg,NULL,0,0))
    {
    的TranslateMessage(MSG);
    DispatchMessage函数(MSG);
    }

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

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

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

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

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

创建一个成员变量as

CProgressCtrl m_progress;

使用进度条ID在DoDataExcchange中的DDX_Control中添加m_progress

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

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

暂无
暂无

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

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