显示来自 Office 外接程序中线程的 WPF 弹出窗口

本文关键字:线程 WPF 窗口 程序 Office 显示 | 更新日期: 2023-09-27 18:34:53

我正在尝试显示一个 WPF 弹出窗口,该弹出窗口将指示一些进度:

问题是在 Thread.Sleep 完成之前没有显示弹出窗口,这只是一个例子,在我的程序中我有复杂的 IO 和 DB 逻辑需要同步执行,并且需要在弹出窗口中显示进度。

这是我的示例代码:

    private ProgressBar m_ProgressBar;
    private void buttonDoWork_Click(object sender, RoutedEventArgs e)
    {
        var progressPopup = new Popup { PopupAnimation = PopupAnimation.Fade, StaysOpen = true, Height = 150, Width = 260 };
        m_ProgressBar = new ProgressBar
                              {
                                  HorizontalAlignment = HorizontalAlignment.Stretch,
                                  VerticalAlignment = VerticalAlignment.Stretch
                              };
        progressPopup.Child = m_ProgressBar;
        progressPopup.IsOpen = true;
        Thread.Sleep(5000);
        this.m_ProgressBar.Value = 25;
        Thread.Sleep(5000);
        this.m_ProgressBar.Value = 50;
        Thread.Sleep(5000);
        this.m_ProgressBar.Value = 75;
        Thread.Sleep(5000);
        this.m_ProgressBar.Value = 100;
    } 

更新

问题是阻塞主线程的逻辑需要留在主线程上,我无能为力。有没有办法在单独的线程上运行弹出窗口?

显示来自 Office 外接程序中线程的 WPF 弹出窗口

使用

Dispather.BeginInvoke(new Action(()=>{ this.m_ProgressBar.Value = progress; });

以更新 UI 线程上的进度条。

一般来说,你不应该像这样编织你的代码(UI和逻辑混淆了(

可以使用后台工作线程或通过引发事件来报告进度的任务。

编辑

澄清一下:公开从视图模型/代码更改的数据并引发事件 (属性更改(,以便可以将 UI 绑定到这些值。这将允许您将 UI 和代码分开。

我会使用 UI 线程和后台线程的拆分非常清晰的BackgroundWorker

例如,使用它,可以登录到 ProgressChanged 事件(属于 UI 线程(,并执行任何要通知用户有关后台进程的操作。

问题是 WPF 要求消息循环旋转,以便它可以调度消息以进行显示、绘制、响应事件等。您必须构建代码,以便buttonDoWork_Click尽快退出。如果不这样做,则整个UI将冻结。

此外,在单个方法中增加进度值基本上没有任何作用。从消息循环的角度来看,进度值只包含一个值...100. 这是您在点击事件结束之前写入ProgressBar的最后一个值。这是进度条在最终允许它自行刷新时知道的唯一值。

您需要从 UI 线程中获取长时间运行的操作。这是我的建议。

  • 使用 Task 类在工作线程上启动操作。
  • 让工作线程将进度信息发布到简单变量。
  • 让 UI 线程按您选择的时间间隔通过计时器轮询进度信息。相应地更新ProgressBar