Я разрабатываю настольное приложение WPF на С# 4.0, которое должно обрабатывать множество длительных операций (загрузка данных из БД, расчет симуляций, оптимизация маршрутов и т. д.).
Когда эти длительные операции выполняются в фоновом режиме, я хочу показать диалоговое окно «Подождите». Когда отображается диалоговое окно Please-Wait, приложение должно быть заблокировано, но просто отключать окно приложения не рекомендуется, поскольку все DataGrids потеряют свой статус (SelectedItem
).
То, что у меня есть, пока работает, но есть некоторые проблемы: новый WaitXUI создается с использованием метода Create-factory. Метод Create ожидает текст заголовка и ссылку на главный элемент управления, который должен быть заблокирован. Метод Create устанавливает StartupLocation окна, текст заголовка и хост для блокировки:
WaitXUI wait = WaitXUI.Create("Simulation running...", this);
wait.ShowDialog(new Action(() =>
{
// long running operation
}));
Затем с помощью перегруженного метода ShowDialog можно отобразить WaitXUI. Перегрузка ShowDialog ожидает действие, которое завершает длительную операцию.
В перегрузке ShowDialog я просто запускаю действие в его собственном потоке, а затем отключаю элемент управления хоста (устанавливаю 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.
- Иногда диалоговое окно вообще не появляется, хотя поток все еще работает.
Это основные проблемы, которые приходят мне на ум в данный момент. Как можно улучшить эту концепцию или какие другие методы можно использовать для решения этой проблемы?
Заранее спасибо!