在我的应用程序中,我有一个图片框和 2 个按钮(“是”和“否”)。Yes 将 1 添加到结果列表中,No 添加 0 并且都转到下一张图片。现在我需要在应用程序中实现一个计时器,如果没有提供答案,它会使图片转到下一个。我想为此使用后台工作人员。
当我不单击按钮时,下面的代码可以很好地切换图片。单击按钮会冻结 UI,因为后台工作人员保持“忙碌”状态。我确实知道 CancelAsync 不会立即停止后台工作程序,但实际上会触发 DoWork 中的返回语句。
所以我的问题是为什么后台工作人员一直很忙,或者我在这里完全走错了路?
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Counter = 0;
_backgroundWorker = new BackgroundWorker();
_backgroundWorker.DoWork += _backgroundWorker_DoWork;
_backgroundWorker.WorkerSupportsCancellation = true;
_backgroundWorker.RunWorkerAsync();
}
private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bgw = sender as BackgroundWorker;
GoToNextItem(); //Show next picture
while (!bgw.CancellationPending)
{
_getNext = false;
Stopwatch sw = Stopwatch.StartNew();
//Wait interval-time
while (!_getNext)
{
if ((sw.ElapsedMilliseconds > Test.Interval * 1000) && !bgw.CancellationPending)
{
_getNext = true;
}
if (bgw.CancellationPending)
{
e.Cancel = true;
return; //Breakpoint is hit here
}
}
if (_getNext)
{
Result.Add(0);
GoToNextItem();
}
}
e.Cancel = true;
}
private void btnNo_Click(object sender, EventArgs e)
{
_backgroundWorker.CancelAsync();
Result.Add(0);
while (_backgroundWorker.IsBusy)
{
_backgroundWorker.CancelAsync();
System.Threading.Thread.Sleep(20);
}
_backgroundWorker.RunWorkerAsync();
}
private void btnYes_Click(object sender, EventArgs e)
{
_backgroundWorker.CancelAsync();
Result.Add(1);
while (_backgroundWorker.IsBusy) //Stays busy ==> UI freezes here
{
_backgroundWorker.CancelAsync();
System.Threading.Thread.Sleep(20);
}
_backgroundWorker.RunWorkerAsync();
}
编辑
按照@Servy 的建议,使用计时器更改了代码。有关 backgroundworker-question 的更多详细信息,请阅读已接受答案的评论。