首页 文章

从办公室加载项中的线程显示WPF弹出窗口

提问于
浏览
1

我正在尝试显示一个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;
    }

Update

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

3 回答

  • 0

    使用

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

    更新UI线程上的进度条 .

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

    您可以使用BackgroundWorker或通过引发事件来报告进度的任务 .

    EDIT

    澄清:暴露从ViewModel /代码更改的数据并引发事件(PropertyChanged),以便您可以将UI绑定到这些值 . 这将允许您保持UI和代码分离 .

  • 0

    我会使用 BackgroundWorker ,其中UI线程和后台线程的拆分非常清楚 .

    例如,使用它可以签署 ProgressChanged 事件(属于UI线程)并执行任何您想要通知用户后台进程的事情 .

  • 4

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

    此外,在单个方法内增加进度值基本上什么都不做 . 从消息循环的角度来看,进度值仅包含单个值... 100 . 这是您在点击事件结束前写入 ProgressBar 的最后一个值 . 这是进度条最终允许刷新自身时所知道的唯一值 .

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

    • 使用 Task 类在工作线程上启动操作 .

    • 让您的工作线程将进度信息发布到一个简单变量 .

    • 在您选择的时间间隔内通过计时器对进度信息进行UI线程轮询 . 相应地更新 ProgressBar .

相关问题