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

C#在关闭应用程序之前,如何让后台工作人员完成保存应用程序状态,c#,multithreading,winforms,C#,Multithreading,Winforms,在C#桌面应用程序中,负责保存应用程序状态的backgroundworker在两种情况下被调用。在应用程序运行时执行一次。那很好。另一种情况是,在关闭应用程序时,会调用backgroundworker来保存应用程序状态,但在开始保存之前,应用程序将关闭,并且不会保存任何内容 我试图通过在DoWork和RunWorkerCompleted中使用AutoReset事件类来解决这个问题,但没有成功,因为应用程序在backgroundworker可以保存任何东西之前关闭了 问题是-如何让主线程等待bac

在C#桌面应用程序中,负责保存应用程序状态的backgroundworker在两种情况下被调用。在应用程序运行时执行一次。那很好。另一种情况是,在关闭应用程序时,会调用backgroundworker来保存应用程序状态,但在开始保存之前,应用程序将关闭,并且不会保存任何内容

我试图通过在DoWork和RunWorkerCompleted中使用AutoReset事件类来解决这个问题,但没有成功,因为应用程序在backgroundworker可以保存任何东西之前关闭了

问题是-如何让主线程等待backgroundworker完成保存

private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
{
    this.saveAHToolStripMenuItem_Click(this, e);
}

private void saveAHAsToolStripMenuItem_Click(object sender, EventArgs e)
{
    this.backgroundWorkerMain1.RunWorkerAsync(args);
}

private void backgroundWorkerMain1_DoWork(object sender, DoWorkEventArgs e)
{
    saveMethod();
}

private void backgroundWorkerMain1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    showResultOfSaving();
}

将SaveState代码放在一个单独的方法中会更干净,该方法在后台工作程序中调用,并在关闭应用程序时(同步)调用

或者,您可以基于手动重置事件(ManualResetEvent类)阻止应用程序关闭。

是WinForms吗

也许你可以注册参加一次失败的活动。 在其中,将私有属性IsClosing设置为true。 将eventhandler e标记为e.Handled=true

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

编辑:


只是在那里抛出一个想法。 可能是主窗体上的一个不稳定的DateTime属性。 (注意-DateTimes在出现时不能是易变的,因此可以使用字符串表示)

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

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

例如:

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

然而,这并不能防止进程的破坏。杀戮——几乎没有什么可以防止这种破坏。 我所能建议的是,你要以一种明智的方式管理你的储蓄。 每次保存到新文件,保留最后5次保存。 第六次保存时,删除最早的保存等


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

我解决此问题的方法是在backgroundworker异步调用后添加以下命令,直到backgroundworker完成

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

在该事件被触发之前不要关闭:如果您展示了您的一些工作,我们可以提供更多帮助。谢谢您的参考。我已经用基本的代码结构更新了我的问题。在这里,FormClosing在backgroundWorker完成保存之前完成。您好,我在下面的回答中添加了编辑解决方案。我将检查ManualResetEvent是否可以在主线程内部使用而不阻塞它。您的第一个同步建议似乎类似于Baaleos建议将其保存在主关闭方法中。好的,我检查了ManualResetEvent,当我在主线程中调用WaitOne()时,应用程序被挂起,当在DoWork()中调用它时,应用程序在保存之前被关闭。是的,在关闭时,我还考虑将其单独保存在主线程中,但backgroundworker正在保存例程中作为参数传递。我想它可能会被重复的代码弄得很复杂。在保存之前,我要求用户保存或不保存,所以我不需要检查时差。是的,它是WinForms。我不能接受你的建议。在FormClosing()中继续运行后面的语句之前,它将如何启用DoWork()运行?您好,我添加了解决方案,因为EditSolution已共享。如果后台工作人员很忙,我不想返回,但想一直等到它完成。@Saad“解决方案已经共享”是什么意思?如果它对你有帮助,请标记为答案。此外,如果bgWorker正忙,那么返回主线程正是您所需要的。
public volatile string _lastUpdated;
var timeDiff = DateTime.Now - _lastSavedTime;
while (this.backgroundWorkerMain1.IsBusy)
{
    Application.DoEvents();
}