ibm123
ibm123

Reputation: 1254

WPF and background worker

I got a WPF window and i want to do some work in a background thread..

when the work is done i want to do it again.. like a loop with a UI update between

my code:

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());
            }

        }

I know this code isn't good cause i got a threading hell and can't debug it properly

for example.. when the code is running and i click the close button i can see in the event the the worker is busy all the time.. resulting an infinity loop..

 private void Window_Closed(object sender, EventArgs e)
        {

                if (m_worker.IsBusy)
                    m_worker.CancelAsync();

                while(m_worker.IsBusy);
                base.Close();
            }

        }

What am i doing wrong ? Thanks

Upvotes: 0

Views: 993

Answers (3)

Sergei B.
Sergei B.

Reputation: 3227

AFAIK you don't ever mark your work as cancelled in worker_DoWork. Cancellation code in that method should look like the following:

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

Only after that you'll get e.Cancelled==true in completion handler and your loop will stop.


If you think that calling CancelAsync() should set Cancelled to true, you're wrong. Here is decompiled code from BackgroundWorker.CancelAsync():

public void CancelAsync()
{
  if (!this.WorkerSupportsCancellation)
    throw new InvalidOperationException(SR.GetString("BackgroundWorker_WorkerDoesntSupportCancellation"));
  this.cancellationPending = true;
}

As you can see it just sets CancellationPending to true, nothing more. So, you have to check this property in your worker_DoWork as shown in the first snippet.

Upvotes: 1

mlemay
mlemay

Reputation: 1637

If you want to run something in the background, you can use this:

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

The code will be executed when the CPU will be free, so it doesn't affect performance of your main thread.

Upvotes: 0

Reza ArabQaeni
Reza ArabQaeni

Reputation: 4908

clear line :

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

Upvotes: 1

Related Questions