显示来自 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;
}
更新
问题是阻塞主线程的逻辑需要留在主线程上,我无能为力。有没有办法在单独的线程上运行弹出窗口?
使用
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
。