在没有调试器的情况下运行时,ProgressBar 会“卡住”

Posted

技术标签:

【中文标题】在没有调试器的情况下运行时,ProgressBar 会“卡住”【英文标题】:ProgressBar gets 'stuck' when running without debugger 【发布时间】:2011-10-21 14:24:32 【问题描述】:

我正在开发一个 Visual C++ 应用程序,其中一部分是对文件进行解包,因为这可能需要一段时间我实现了一个进度条来反映解包的进度。

使用调试器运行时效果很好,但是当我不使用调试器或从 .exe 文件运行时,进度条始终卡在中途(尽管程序可以正常完成其功能),然后跳转到 100% .

通过打印进度条的值,我发现该值设置正确,但由于某种原因,这没有在视觉上反映出来。

进度条更新的代码是

while (mpeg.GetProgress() < 99)
            Console::Write(this->progressBar->Value);
            this->progressBar->Value = mpeg.GetProgress();
            this->progressBar->Update();
            Sleep(100);
        

这是在程序主线程中完成的。 睡眠会阻止它过快更新,否则无法在控制台中执行此操作。

需要跟踪的函数是mpeg.Depackitise(),它在一个单独的线程中运行,以便不断更新进度条,关于'progress'变量的代码是:

double Mpeg::GetProgress() 
return Mpeg::progress;


void Mpeg::SetProgress(double prog) 
Mpeg::progress = prog;

以下代码在一个 for 循环中,逐包遍历整个文件。 'packet' 变量是当前数据包,'packet_count' 是文件中的数据包总数,这都是在单独的 mpeg.Depackitise() 线程中完成的。

        double Percent = 0.0;

    Percent = ((double)packet / (double)packet_count);
    SetProgress(Percent * 100);

如果有人可以提出一些解决方案来尝试,我们将不胜感激,这已经让我烦恼了一段时间。我在网上找到的一些建议说,使用未初始化的变量可能会导致有/无调试运行之间的差异,但是我找不到任何未初始化的相关变量。

【问题讨论】:

确定窗口的标题栏也变为“无响应”?那是当你的 UI 线程死掉时 Windows 建立的幽灵窗口。不要阻止用户界面。 【参考方案1】:

您绝对不能阻塞 UI 线程。

您正在应用程序的主线程中进行大量计算,这意味着它无法回答消息泵以及在屏幕上绘制/更新控件的图形。

您应该研究多线程和消息传递作为您问题的解决方案。启动一个线程,在那里做耗时的工作,使用回调来更新主线程的进度条(并注意从主线程以外的任何地方直接访问 UI!)。

【讨论】:

+1 由于 Win32 的设计和消息泵的工作方式,它应该始终从主线程访问。 所有计算都在 mpeg.Depackitise() 函数中完成,该函数在单独的线程中运行。进度条更新在主线程中完成,是否也应该在单独的线程中完成? 我无法从除主线程之外的任何其他线程访问进度条,因此我不确定如何以除了我已经完成的任何方式来更新它。 @marasmuse 听起来你用来更新进度条的代码实际上是阻塞的。即,您正在根据另一个线程中长时间运行的操作的状态循环和更新进度条。这同样不正确。 好的,这听起来会导致我看到的问题,但是如果没有这个,我怎么能定期更新进度条呢?我不能在单独的线程中执行此操作,因为它只能从主线程访问,有什么想法吗?

以上是关于在没有调试器的情况下运行时,ProgressBar 会“卡住”的主要内容,如果未能解决你的问题,请参考以下文章

Just-In-Time调试器在没有必要的安全权限的情况下启动

如何在没有 Visual Studio 的情况下进行调试?

如何在没有错误消息的情况下调试 ctypes

使用 ProgressBar 和自定义按钮显示 TaskDialog 时出错

Xcode 5 在没有调试器的情况下不从标准输入读取

更改在运行时添加的 ProgressBar 的宽度