【发布时间】:2010-12-12 17:53:15
【问题描述】:
我的应用程序可能需要一段时间才能连接到数据库。这种连接是通过单个库函数调用建立的,即我不能将进度更新放在那里并进行回调或类似的东西。
我的想法是在连接到数据库之前在单独的线程中创建一个带有进度条的对话框。此对话框将使用CProgressCtrl::StepIt() 不断更改进度状态,以便用户看到正在发生的事情。
在设置好对话框并完成它的事情之后,我想从主线程调用数据库连接函数。
连接功能完成后,我想停止进度条线程。
让我画一幅画:
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-connection 代码并在完成后将运行标志设置为
false。 - 当主线程退出循环时,它可以像以前一样处理错误。
缺点:将鼠标移到窗口上不起作用。它是看不见的。因此不能使用取消按钮或其他交互式对话框元素。不过,我可以忍受。
由于您喜欢该图表,现在它的外观如下:
CMyApp:: WorkerThread
InitInstance() .
| .
| .
Create Dialog .
| .
+-Start Thread--+
| |
| Connect
Animate to
Progress DB
Bar |
| |
+-Thread Ends---+
| .
Destroy Dlg .
| .
【问题讨论】:
-
您可以在 ANSI 应用程序中调用 SetMarquee(),但这对您没有帮助,因为在主线程上也会调用动画进度条的计时器
-
在我的 afxcmn.h 中看起来像这样: ** if (WIN32_WINNT >= 0x0501) && defined(UNICODE) \n BOOL SetMarquee(_In BOOL fMarqueeMode, In int nInterval); \n #endif // _WIN32_WINNT >= 0x0501 && defined(UNICODE) \n ** 这就是我不能调用它的原因。
-
标题中的一群,复制该代码(它只是发送一条消息)并使用它。
-
我现在在一个单独的测试项目中进行了尝试:必须满足以下所有条件才能使选取框工作: 1. 在资源属性(PBS_MARQUEE)中启用“选取框”。 2. 向控件发送消息 PBM_SETMARQUEE。 3. 使用 Unicode 支持编译。
-
您可以通过使用模态对话框和计时器来摆脱这个缺点。在 OnInitDialog 中启动线程并设置计时器。在 OnTimer 中调用 StepIt 来更新进度。但请确保您控制了关闭对话框的所有可能方式,要么不让用户访问,要么停止线程。
标签: c++ multithreading mfc dialog progress-bar