0

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

3
  • Could you show how do you handle pending cancellation in you worker_DoWork method? Commented Nov 17, 2011 at 20:17
  • I dont handle it.. only in the RunWorkerCompleted event Commented Nov 17, 2011 at 20:22
  • Read my answer below. You need to set e.Cancelled to true by yourself. Commented Nov 17, 2011 at 20:24

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, i added it, but it didn't fix my problem.. when the window is close i return to the parent window window2.ShowDialog();.. only after the window has been closed the background thread has stopped. The crash come only after i call window2.ShowDialog() for the second time.. maybe the problem isn't in the background thread , but in the window navigation.. what do you think ?
If so, this crash issue could be completely different and it's better to create another question.
thanks, you are right. i had to dispose something in the window that did not dispose itself
1

clear line :

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

3 Comments

This line is only for debug.. what happens is that i'm back to the previous window but the background thread is active.. <pre> Window window = new Window2(selectedTitle, m_selectedCamID); window.Owner = this; window.ShowDialog(); <code> after the the ShowDialog the debugger jump back to the background thread in window2's code
@RedHat: It's obvious that infinite loop is at that line. The question was - why?
CancelAsync() Requests cancellation of a pending background operation, and may be little time wait to cancel completed.
0

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.

1 Comment

Dispatcher.Invoke will affect the performance, maybe not of the mainthread but of the workthread so he should use the ReportProgress-Methode if he want's to show some sort of progress

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.