我一直在通过线程(BackgroundWorker
和其他人)了解这个问题是如何面对的,以及如何保持UI响应。我设法这样做但后来我意识到这不是我想要的。实际上我需要的是在执行长操作时显示动画ProgressBar
。 (我不需要/想要更新UI,因为在该操作中我导出所有图形表示并且绘图仪不断更新。)
我正在考虑在执行操作时使用进度条弹出Dialog。问题是我得到了这个例外:
The calling thread cannot access this object because a different thread owns it
对此有很多疑问,答案是使用Dispatcher
:
Dispatcher.CurrentDispatcher.Invoke(() => myOperation(), DispatcherPriority.Normal);
以下是做了什么:
我正在使用Modern UI,有一个名为ModernDialog的Dialog,它只是一个奇特的对话框:
class DialogProgress
{
public ModernDialog progressDlg = new ModernDialog();
public DialogProgress()
{
ProgressBar bar = new ProgressBar();
bar.IsIndeterminate = true;
bar.Width = 150;
StackPanel content = new StackPanel();
content.Children.Add(bar);
progresoDlg.Content = content ;
//Thread paralel = new Thread(() => myOperation());
//paralel.SetApartmentState(ApartmentState.STA);
//paralel.Start();
Dispatcher.CurrentDispatcher.Invoke(() => myOperation(), DispatcherPriority.Normal);
}
void myOperation()
{
progresoDlg.ShowDialog();
}
}
我知道我在那里混合东西,有Threads和Dispatcher,但我无法弄清楚如何使用它们。
以下是我如何调用此对话框:
public void MyLongMethod()
{
DialogProgress progress = new DialogProgress();
}
如果我只使用Dispatcher,则会显示对话框并且正在设置动画条,但MyLongMethod不起作用(它在关闭对话框后启动)。
如果我使用Threads,我会得到提到的异常。
我该如何解决这个问题?
(P.D。使用对话框只是一个建议,如果进度条在UI中,我会很高兴,当长方法开始/结束时我切换可见性)
答案 0 :(得分:2)
Dispatcher.CurrentDispatcher.Invoke(...);
这是错误的,因为您使用了Invoke(),在调用的方法完成运行之前它不会返回。这需要一段时间,ShowDialog()是一个阻塞调用,在用户关闭对话框之前无法完成。
简单的解决方法是使用BeginInvoke()代替。
答案 1 :(得分:-1)
假设ModernDialog
是WPF Window
,ShowDialog方法在关闭之前不会返回。在调用操作并返回之前,Invoke也不会返回。您需要使用Show代替ShowDialog
,或使用BeginInvoke代替Invoke
。我会使用Show
,因为除非您等待用户通过单击对话框按钮进行响应,否则ShowDialog
没有任何意义。