Следующий сценарий:
В приложении WPF программа вызывает Log.Write для постановки в очередь сообщений, которые будут записаны на разные выходы (DB, File) в другом потоке. Количество написанных наборов данных может варьироваться от небольших сумм до 50000 и более записей. Пользователь может закрыть приложение каждый раз. Чтобы гарантировать, что все данные будут записаны, даже если пользователь пытается закрыть приложение в Application.Exit вызывается функция Log.Dispose из потока пользовательского интерфейса. Поток пользовательского интерфейса присоединяется к фоновому потоку для ожидания записи всех данных. Это происходит в приложении. Выход.
Теперь было бы здорово показать диалог прогресса во время этого процесса. Проблема в том, что прогресс не движется со следующим кодом:
// Initialize
Log.CurrentInstance.DisposingProgress += new EventHandler<DisposingEventArgs>(Log_DisposingProgress)
// initialize dialog
// ...
_dialog.Show();
Log.Dispose(); // in this method data is written back, threads closed and so on
protected void SetPercentage(DisposingEventArgs e)
{
if (e.DisposingCompleted)
_dialog.Close();
_dialog.Value = e.Percentage;
}
// this function is called by a timer which checks the status of the disposing process
protected void Log_DisposingProgress(object sender, DisposingEventArgs e)
{
_dialog.Dispatcher.Invoke(new Action<DisposingEventArgs>(SetPercentage), e);
}
Я догадался, что проблема возникает, потому что я вызываю Log.Dipose из UI Thread. Поэтому я попытался вызвать Log.Dispose с
new Action(Log.Dispose).BeginInvoke(null, null);
Это заставит индикатор выполнения двигаться, если я вызову Dispose для события, такого как нажатие кнопки, и приложение все еще будет запущено. Если я вызываю его из Application.Exit, я должен предотвратить закрытие приложения. Я пробую это с
new Thread(() => { while(_isDisposing) Thread.Sleep(100); }
но индикатор выполнения все еще не движется в этом случае.
Я попытался запустить другой поток пользовательского интерфейса, в котором должен отображаться диалог прогресса, но программа просто закроется. Поскольку вызов выключения будет все еще обработан, когда я звоню Dispatcher.Run()
.