以下情景:
在WPF应用程序中,程序调用Log.Write将消息排入队列,这些消息将写入另一个线程中的不同输出(DB,File)。写入的数据集数量可以从少量到50000或更多条目变化。用户每次都可以关闭应用程序。即使用户尝试在Application.Exit上关闭应用程序,也要确保写入所有数据。从UI线程调用Log.Dispose函数。 UI线程加入后台线程,等待所有数据写入。这发生在Application.Exit。
上现在,在此过程中显示进度对话框会很棒。问题是,进度没有随着以下代码而移动:
// 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);
}
我猜到了问题,因为我从UI Thread调用了Log.Dipose。所以我试着用
调用Log.Disposenew Action(Log.Dispose).BeginInvoke(null, null);
如果我在按钮单击等事件上调用Dispose并且应用程序仍在运行,这将使进度条移动。如果我从Application.Exit调用它,我必须阻止应用程序关闭。我试试
new Thread(() => { while(_isDisposing) Thread.Sleep(100); }
但在这种情况下,进度条仍然没有移动。
我尝试启动另一个应该显示进度对话框的UI线程,但程序将关闭。因为当我拨打Dispatcher.Run()
时仍会处理关机通话。
答案 0 :(得分:1)
经过较长时间后,我再试一次。以下代码执行我想要实现的目标:
Log.CurrentInstance.DisposingProgress += new EventHandler<DisposingEventArgs>(Log_DisposingProgress);
var thread = new Thread(() =>
{
...
_dialog.Show();
while (true)
{
lock (currentEventArgsLock)
{
if (currentEventArgs != null)
{
_dialog.Value = currentEventArgs.Percentage;
if (currentEventArgs.DisposingCompleted)
{
_dialog.Close();
return;
}
}
}
Thread.Sleep(20);
}
});
var thread2 = new Thread(() =>
{
Log.Dispose();
});
thread.Start();
thread2.Start();
// make sure both threads finished
thread.Join();
thread2.Join();
return;
/// <summary>
/// This function is called to notify about progress changes during disposing of Log.
/// </summary>
/// <param name="sender">The sender object.</param>
/// <param name="e">The event arguments</param>
protected void Log_DisposingProgress(object sender, DisposingEventArgs e)
{
lock (currentEventArgsLock)
{
currentEventArgs = e;
}
}
答案 1 :(得分:0)
您可以尝试使用SystemEvents.SessionEnding事件:
http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.sessionending.aspx