【发布时间】:2014-02-12 16:53:33
【问题描述】:
我正在用 c# 4.0 开发一个 WPF 桌面应用程序,它必须处理大量长时间运行的操作(从数据库加载数据、计算模拟、优化路线等)。
当这些长时间运行的操作在后台运行时,我想显示一个 Please-Wait 对话框。当显示 Please-Wait 对话框时,应用程序应该被锁定,但仅仅禁用应用程序窗口并不是一个好主意,因为所有 DataGrids 都会失去它们的状态 (SelectedItem)。
到目前为止,我的工作有效,但存在一些问题: 使用 Create-factory 方法创建一个新的 WaitXUI。 Create 方法需要标题文本和对应该锁定的宿主控件的引用。 Create 方法设置窗口的 StartupLocation、标题文本和要锁定的主机:
WaitXUI wait = WaitXUI.Create("Simulation running...", this);
wait.ShowDialog(new Action(() =>
{
// long running operation
}));
使用重载的 ShowDialog 方法可以显示 WaitXUI。 ShowDialog 重载确实需要一个包含长时间运行操作的 Action。
在 ShowDialog 重载中,我只是在自己的线程中启动 Action,然后禁用主机控件(将 Opacity 设置为 0.5 并将 IsEnabled 设置为 false)并调用基类的 ShowDialog。
public bool? ShowDialog(Action action)
{
bool? result = true;
// start a new thread to start the submitted action
Thread t = new Thread(new ThreadStart(delegate()
{
// start the submitted action
try
{
Dispatcher.UnhandledException += Dispatcher_UnhandledException;
Dispatcher.Invoke(DispatcherPriority.Normal, action);
}
catch (Exception ex)
{
throw ex;
}
finally
{
// close the window
Dispatcher.UnhandledException -= Dispatcher_UnhandledException;
this.DoClose();
}
}));
t.Start();
if (t.ThreadState != ThreadState.Stopped)
{
result = this.ShowDialog();
}
return result;
}
private new bool? ShowDialog()
{
DisableHost();
this.Topmost = true;
return base.ShowDialog();
}
private void DisableHost()
{
if (host != null)
{
host.Dispatcher.Invoke(new Action(delegate()
{
this.Width = host.Width - 20;
host.Cursor = Cursors.Wait;
host.IsEnabled = false;
host.Opacity = 0.5;
}));
}
}
这里有问题:
- 禁用主机控件会导致状态信息丢失(SelectedItems...)
- 当线程在 WaitXUI 显示几毫秒后结束时,WaitXUI 有时只显示几毫秒
- 虽然线程仍在运行,但有时对话框根本不出现
这些是我目前想到的主要问题。如何改进这个概念,或者可以采用哪些其他方法来解决这个问题?
提前致谢!
【问题讨论】:
-
甚至不会作为问题发布,因为它很难看。将每个控件设置为 IsEnabled = false。或者在 Window 中捕获任何输入并设置 e.handled = true。
-
这肯定是重复的。
-
@Blam 但这并不能解决我的任何问题。
-
@Akane 有类似的问题,但都有其他(较低)要求!将我的问题作为重复而不发布解决方案没有帮助;-)