Reputation: 1254
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
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
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
Reputation: 4908
clear line :
while(m_worker.IsBusy);//may be go to infinite loop
Upvotes: 1