C#关闭应用程序之前如何让后台工作者完成保存应用程序状态

时间:2016-01-27 13:10:01

标签: c# multithreading winforms

在C#桌面应用程序中,在两种情况下调用负责保存应用程序状态的后台工作程序。一旦应用程序运行。这很好。其他当应用程序关闭时,调用backgroundworker来保存应用程序状态,但在开始保存之前,应用程序将关闭,不会保存任何内容。

我试图通过在DoWork和RunWorkerCompleted中使用AutoReset事件类来解决它但是没有工作,因为在backgroundworker之前关闭应用程序可以保存任何东西。

问题是 - 如何让主线程等到后台工作完成保存?

input,
select,
textarea {
    max-width: 280px;
}

4 个答案:

答案 0 :(得分:1)

是WinForms吗?

也许您可以注册OnClosing事件。 在其中,将私有属性IsClosing设置为true。 将事件处理程序e标记为e.Handled = true。

注册到BackgroundWorker事件RunWorkerCompleted。在其中,检查是否设置了IsClosing属性,在那种情况下是MainForm.Close()应用程序。

编辑:

using System;
using System.Threading;
using System.Windows.Forms;
using System.ComponentModel;

namespace BgWorker
{
    public partial class Form1 : Form
    {
        BackgroundWorker _bgWorker;
        bool _iNeedToCloseAfterBgWorker;

        public Form1()
        {
            InitializeComponent();
        }

        void Form1_Load(object sender, EventArgs e)
        {
            _bgWorker = new BackgroundWorker();
            _bgWorker.DoWork += _bgWorker_DoWork;
            _bgWorker.RunWorkerCompleted += _bgWorker_RunWorkerCompleted;
        }

        void _bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("Done!");

            if (_iNeedToCloseAfterBgWorker)
                Close();
        }

        void _bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // Do long lasting work
            Thread.Sleep(2000);
        }

        void btnWorkIt_Click(object sender, EventArgs e)
        {
            // Note how the Form remains accessible
            _bgWorker.RunWorkerAsync();
        }

        void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_iNeedToCloseAfterBgWorker || _bgWorker.IsBusy) return;
            e.Cancel = true;
            _iNeedToCloseAfterBgWorker = true;
            _bgWorker.RunWorkerAsync();
        }
    }
}

答案 1 :(得分:0)

将SaveState代码放在一个单独的方法中会更加清晰,该方法是从后台工作程序调用的,并且在关闭应用程序时(同步)。

或者,您可以根据手动重置事件(ManualResetEvent-class)阻止应用程序关闭。

答案 2 :(得分:0)

只是抛出一个想法。 也许是MainForm上的一个不稳定的DateTime属性。 (注意 - DateTimes不会出现波动,因此您可以使用字符串表示法)

public volatile string _lastUpdated;

每次在后台工作线程上执行save事件时,此属性都会更新。

OnClose将检查DateTime.Now与存储日期时间之间的时差。

例如:

var timeDiff = DateTime.Now - _lastSavedTime;

如果OnClose检测到timeDiff.TotalSeconds是< 30(不到30秒) 然后,您可以在关闭事件完成之前从主线程手动触发保存事件。

然而,这不能防止Process.Kill - 很少可以防止这种情况发生。 我所能建议的是,您以聪明的方式管理您的存储。 例如:每次保存到新文件,保留最后5次保存。 进行第6次保存时,删除最旧的保存等

这是为了说明Process.Kill场景可能发生的潜在损坏。意味着如果30秒备份失败,您仍将至少有60秒备份。

答案 3 :(得分:0)

我对这个问题的解决方法是等待直到后台工作人员通过在backgroundworker异步调用之后添加以下内容来完成。

while (this.backgroundWorkerMain1.IsBusy)
{
    Application.DoEvents();
}