在C#桌面应用程序中,在两种情况下调用负责保存应用程序状态的后台工作程序。一旦应用程序运行。这很好。其他当应用程序关闭时,调用backgroundworker来保存应用程序状态,但在开始保存之前,应用程序将关闭,不会保存任何内容。
我试图通过在DoWork和RunWorkerCompleted中使用AutoReset事件类来解决它但是没有工作,因为在backgroundworker之前关闭应用程序可以保存任何东西。
问题是 - 如何让主线程等到后台工作完成保存?
input,
select,
textarea {
max-width: 280px;
}
答案 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();
}