3 回答
TA贡献1798条经验 获得超7个赞
如果我了解您的要求正确,则可以执行以下操作(代码未经测试,但显示了总体思路):
private BackgroundWorker worker = new BackgroundWorker();
private AutoResetEvent _resetEvent = new AutoResetEvent(false);
public Form1()
{
InitializeComponent();
worker.DoWork += worker_DoWork;
}
public void Cancel()
{
worker.CancelAsync();
_resetEvent.WaitOne(); // will block until _resetEvent.Set() call made
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
while(!e.Cancel)
{
// do something
}
_resetEvent.Set(); // signal that worker is done
}
TA贡献1878条经验 获得超4个赞
此响应有问题。UI需要在您等待时继续处理消息,否则它将不会重新绘制,如果后台工作人员花很长时间来响应取消请求,这将是一个问题。
第二个缺陷是,_resetEvent.Set()如果工作线程引发异常-将使主线程无限期地等待-将永远不会被调用-但是,可以使用try / finally块轻松修复此缺陷。
一种方法是显示一个模态对话框,其中包含一个计时器,该计时器可反复检查后台工作人员是否已完成工作(或在您的情况下完成取消)。后台工作人员完成操作后,模态对话框将控制权返回给您的应用程序。在这种情况发生之前,用户无法与UI进行交互。
另一种方法(假设您最多打开一个无模式窗口)是设置ActiveForm.Enabled = false,然后在Application,DoEvents上循环,直到后台工作程序完成取消为止,然后可以再次设置ActiveForm.Enabled = true。
TA贡献1875条经验 获得超3个赞
几乎所有人都对这个问题感到困惑,并且不了解如何使用工人。
考虑一个RunWorkerComplete事件处理程序:
private void OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!e.Cancelled)
{
rocketOnPad = false;
label1.Text = "Rocket launch complete.";
}
else
{
rocketOnPad = true;
label1.Text = "Rocket launch aborted.";
}
worker = null;
}
一切都很好。
现在出现了这样一种情况,即呼叫者需要中止倒计时,因为他们需要执行火箭的紧急自毁。
private void BlowUpRocket()
{
if (worker != null)
{
worker.CancelAsync();
WaitForWorkerToFinish(worker);
worker = null;
}
StartClaxon();
SelfDestruct();
}
还有一种情况,我们需要打开火箭的检修门,而不是在倒计时时:
private void OpenAccessGates()
{
if (worker != null)
{
worker.CancelAsync();
WaitForWorkerToFinish(worker);
worker = null;
}
if (!rocketOnPad)
DisengageAllGateLatches();
}
最后,我们需要给火箭加油,但是在倒数计时中这是不允许的:
private void DrainRocket()
{
if (worker != null)
{
worker.CancelAsync();
WaitForWorkerToFinish(worker);
worker = null;
}
if (rocketOnPad)
OpenFuelValves();
}
没有等待工人取消的能力,我们必须将所有三个方法移至RunWorkerCompletedEvent:
private void OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (!e.Cancelled)
{
rocketOnPad = false;
label1.Text = "Rocket launch complete.";
}
else
{
rocketOnPad = true;
label1.Text = "Rocket launch aborted.";
}
worker = null;
if (delayedBlowUpRocket)
BlowUpRocket();
else if (delayedOpenAccessGates)
OpenAccessGates();
else if (delayedDrainRocket)
DrainRocket();
}
private void BlowUpRocket()
{
if (worker != null)
{
delayedBlowUpRocket = true;
worker.CancelAsync();
return;
}
StartClaxon();
SelfDestruct();
}
private void OpenAccessGates()
{
if (worker != null)
{
delayedOpenAccessGates = true;
worker.CancelAsync();
return;
}
if (!rocketOnPad)
DisengageAllGateLatches();
}
private void DrainRocket()
{
if (worker != null)
{
delayedDrainRocket = true;
worker.CancelAsync();
return;
}
if (rocketOnPad)
OpenFuelValves();
}
现在,我可以这样编写代码,但是我不会。我不在乎,我只是不在乎。
- 3 回答
- 0 关注
- 470 浏览
添加回答
举报