我正在使用C# 4.0开发一个WPF桌面应用程序,需要处理大量的长时间运行的操作(从数据库加载数据、计算模拟、优化路线等)。
当这些长时间运行的操作在后台运行时,我想显示一个“请稍候”对话框。当“请稍候”对话框显示时,应用程序应该被锁定,但仅禁用应用程序窗口并不是一个好主意,因为所有的DataGrid都会失去它们的状态(SelectedItem)。
目前我所做的工作有一些问题: 使用Create工厂方法创建了一个新的WaitXUI。Create方法期望标题文本和要锁定的主机控件的引用。Create方法设置窗口的启动位置、标题文本和要锁定的主机:
这里存在以下问题:
提前感谢!
当这些长时间运行的操作在后台运行时,我想显示一个“请稍候”对话框。当“请稍候”对话框显示时,应用程序应该被锁定,但仅禁用应用程序窗口并不是一个好主意,因为所有的DataGrid都会失去它们的状态(SelectedItem)。
目前我所做的工作有一些问题: 使用Create工厂方法创建了一个新的WaitXUI。Create方法期望标题文本和要锁定的主机控件的引用。Create方法设置窗口的启动位置、标题文本和要锁定的主机:
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有时只显示几毫秒
- 有时尽管线程仍在运行,但对话框根本不会出现
提前感谢!