【问题标题】:Write data on Application.Exit and show progress dialog在 Application.Exit 上写入数据并显示进度对话框
【发布时间】:2011-02-11 16:31:53
【问题描述】:

以下场景:

在 WPF 应用程序中,程序调用 Log.Write 将消息排入队列,这些消息将写入另一个线程中的不同输出(DB、文件)。写入的数据集数量可以从少量到 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 线程调用 Log.Dipose。所以我尝试用

调用 Log.Dispose
new Action(Log.Dispose).BeginInvoke(null, null);

如果我在按钮单击等事件上调用 Dispose 并且应用程序仍在运行,这将使进度条移动。如果我从 Application.Exit 调用它,我必须阻止应用程序关闭。我试试

new Thread(() => { while(_isDisposing) Thread.Sleep(100); }

但在这种情况下进度条仍然没有移动。

我尝试启动另一个 UI 线程,其中应该显示进度对话框,但程序将关闭。因为当我调用Dispatcher.Run()时,仍然会处理关闭调用。

【问题讨论】:

  • 您是否考虑过记录更改并在程序启动时进行更新?换句话说,不是阻止应用程序完全关闭,而是在程序关闭后运行时执行它。
  • 我不知道如何跟踪这些变化?似乎这个任务的复杂性很高,只是为了写回日志记录。即使它可能很多。也许我误解了你的想法。

标签: c# .net wpf multithreading dispatcher


【解决方案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;
    }
}

【讨论】:

    【解决方案2】:

    【讨论】:

    • 此事件“在用户尝试注销或关闭系统时发生。”我只需要确保在程序关闭时将数据写入数据库。
    猜你喜欢
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    • 2013-04-22
    • 2017-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多