WPF和后台工作人员

本文关键字:工作人员 后台 WPF | 更新日期: 2023-09-27 18:14:55

我有一个WPF窗口,我想在后台线程做一些工作。

当工作完成后,我想再做一遍。比如在 之间有UI更新的循环我代码:

private void InitializeBackgroundWorker()
        {
            m_stopCamera = false;
            m_worker = new BackgroundWorker();
            m_worker.DoWork += new DoWorkEventHandler(worker_DoWork);
            m_worker.RunWorkerCompleted += new     RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
            m_worker.WorkerSupportsCancellation = true;
        }
unsafe void worker_DoWork(object sender, DoWorkEventArgs e)
{
  // my work....
  e.Result = new MyResultClass(p1,p2..);
}
private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
                return;

            if (e.Error != null)
            {
                Logger.LogException(e.Error.ToString());
                Window_Closed(this, new EventArgs());
            }
            try
            {
                //UI work..
                DetectionResult result = e.Result as DetectionResult;
                if (result.Cancel == true)
                {
                    m_DetectedObjID = result.DetectionID;
                    // PlaySound();
                    audio_MediaEnded(this, new EventArgs());
                }
                else
                     ((BackgroundWorker)sender).RunWorkerAsync();
            }
            catch (Exception ex)
            {
                Logger.LogException(ex.ToString());
                Window_Closed(this,new EventArgs());
            }
        }

我知道这段代码不是很好,因为我有一个线程地狱,不能正确调试它

例如

. .当代码运行时,我单击关闭按钮,我可以在事件中看到这个工人一直很忙。导致无限循环…

 private void Window_Closed(object sender, EventArgs e)
        {
                if (m_worker.IsBusy)
                    m_worker.CancelAsync();
                while(m_worker.IsBusy);
                base.Close();
            }
        }

我做错了什么?由于

WPF和后台工作人员

我知道你从来没有在worker_DoWork中将你的工作标记为已取消。该方法中的取消代码应该如下所示:

if ((m_worker.CancellationPending == true))
{
   e.Cancel = true;
   return;
}

只有在完成处理程序之后,你才会得到e.Cancelled==true,循环将停止。


如果你认为调用CancelAsync()应该设置取消为真,你错了。下面是BackgroundWorker.CancelAsync():

的反编译代码
public void CancelAsync()
{
  if (!this.WorkerSupportsCancellation)
    throw new InvalidOperationException(SR.GetString("BackgroundWorker_WorkerDoesntSupportCancellation"));
  this.cancellationPending = true;
}

您可以看到,它只是将CancellationPending设置为true,仅此而已。因此,您必须在worker_DoWork中检查此属性,如第一个代码片段所示。

clear line:

while(m_worker.IsBusy);//may be go to infinite loop

如果你想在后台运行一些东西,你可以使用这个:

public void DoEvents()
{
    Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() =>
    {
        code;
        DoEvents();
    }));
}

代码将在CPU空闲时执行,所以它不会影响主线程的性能。