【问题标题】:Showing the Progressbar: the other way round显示进度条:反过来
【发布时间】:2012-09-12 07:04:13
【问题描述】:

通常的做法是在 UI 线程中显示进度窗口(带有进度条)并从工作线程更新进度。

我有很多在 GUI 线程本身中启动和运行的长操作(这会暂时冻结 GUI)。要求是显示所有现有长操作的进度条。通常的解决方案是将长操作作为线程移动并从那里更新进度。但我不确定这些长操作的线程安全性。

有没有办法让我们在另一个线程中显示进度窗口(因此它不会冻结),然后从主 GUI 线程本身更新进度?

【问题讨论】:

  • 我建议从长远来看,您最好将长期运行的代码从 UI 中重构为可以在不同线程上运行的单独类。它将为您省去很多麻烦,并帮助您在将来编写更好的代码。
  • 我也希望这样做。但是这些操作过去是由其他人编写的,涉及文件、数据库、UI 控件和所有易受攻击的非线程安全事物。时间和精力不利于扰乱现状。
  • 我可能会有所不同,但我相信你会比我更清楚地了解复杂性。不过我会认为,你是在把好的开发人员的时间浪费在坏的之后,只是在制作情况更糟。学习重构复杂系统是一项技能,您可以通过实践变得更好。

标签: c# wpf multithreading thread-safety progress-bar


【解决方案1】:

我不知道在另一个线程中显示 ProgressBar 的解决方案,但是您可以尝试一个 hack,让系统从您的长时间运行的操作中执行其操作(更新 UI)。为此,您可以在长时间运行的操作中重复调用以下函数:

public static void DoEvents() {
  DispatcherFrame frame = new DispatcherFrame();
  Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate(object parameter) {
    frame.Continue = false;
    return null;
}), null);
  Dispatcher.PushFrame(frame);
}

但请注意,这不是解决问题的好方法。最好选择合适的设计。

【讨论】:

    【解决方案2】:

    查看thread

    我认为你应该使用Application.DoEvents()

    【讨论】:

    • 这是winforms。 OP 已将其问题标记为 WPF 并且 WPF 没有 Application.DoEvents。这就是我发布替换功能的原因。但如前所述:这只是一种解决方法。
    • 使用Application.DoEvents() 是非常糟糕的做法,可能会导致各种问题,例如重新进入。
    • mmhmm 如果我们想用线程移动 UI 中的进度条,我们应该怎么做?顺便说一句,我为我的回答道歉,我认为这是一个 winform :)
    猜你喜欢
    • 2013-11-30
    • 1970-01-01
    • 2014-05-25
    • 2023-03-10
    • 2016-09-13
    相关资源
    最近更新 更多