我想在计时器刻度事件中调用一个函数,以便它执行直到计时器间隔结束。问题是该函数正在与后台工作程序一起工作,我无法设置e.Cancel = true以在时间到来之前停止执行函数。这是我尝试过的。
private void timer1_Tick_1(object sender, EventArgs e)
{
presenter.RunEngine(); // call the function here
// ...
}
-------------------------------------------------------
public BackgroundWorker worker;
public PresenterClass()
{
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(Worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(Worker_ProgressChanged);
worker.WorkerReportsProgress = true;
worker.WorkerSupportsCancellation = true;
}
private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
DisplayState();
}
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
if (worker.CancellationPending)
{
e.Cancel = true;
worker.ReportProgress(0);
return;
}
worker.RunWorkerAsync(); // I don't think I should call it here, but it doesn't work otherwise
}
public void RunEngine()
{
if (worker.CancellationPending)
{
view.timer.Enabled = false;
view.timer.Stop();
// here I should be able to set e.Cancel = true;
return;
}
double oxygenLevel = _systemEngine.Subsystems.Where(s => s.Article == "Oxygen").First().State.Level;
if (oxygenLevel > 0)
{
ConsumeEngine();
}
else
{
worker.CancelAsync();
}
}
private void ConsumeEngine()
{
Parallel.ForEach(_systemEngine.Subsystems, (currentSystem) =>
{
if (currentSystem is ShieldMatrix)
{
ConsumeShields(currentSystem);
}
else if (currentSystem is WeaponToolbar)
{
ConsumeWeapons(currentSystem);
}
else {
currentSystem.State.Consume();
}
));
worker.ReportProgress(90);
}
private void ConsumeWeapons(BaseModel currentSystem)
{
// ...
}
private void ConsumeShields(BaseModel currentSystem)
{
// ...
}
答案 0 :(得分:0)
我同意其他人评论说有更好的方法来实现这个功能,但如果你仍然继续使用这种方法,那么你需要以某种方式使DoWorkEventArgs可以访问RunEngine方法。例如,您可以在调用RunWorkerAsync方法之前声明一个实例字段存储后台工作程序的args。
//Declare an instance to store the arguments of the background worker
public DoWorkEventArgs DoWorkEventArgsIntance { get; set; }
private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
if (worker.CancellationPending)
{
e.Cancel = true;
worker.ReportProgress(0);
//Clear the DoWorkEventArgs intance
DoWorkEventArgsIntance = null;
return;
}
//Set the instance to the current value of the bw
DoWorkEventArgsIntance = e;
worker.RunWorkerAsync(); // I don't think I should call it here, but it doesn't work otherwise
}
然后在RunEngine方法中,当您需要停止执行时,您将可以访问参数,并且您将能够调用取消。
public void RunEngine()
{
if (worker.CancellationPending)
{
view.timer.Enabled = false;
view.timer.Stop();
// here I should be able to set e.Cancel = true;
//As we stored the value before start the worker, now we can cancel here
DoWorkEventArgsIntance.Cancel = true;
return;
}
double oxygenLevel = _systemEngine.Subsystems.First(s => s.Article == "Oxygen").State.Level;
if (oxygenLevel > 0)
{
ConsumeEngine();
}
else
{
worker.CancelAsync();
}
}
希望这可以帮到你。