BackgroundWorker starts other threads that have an exception. Exception
not caught?
I have a BackgroundWorker that I call from my main UI thread as follows.
On the MainWindow I declare the BackgroundWorker
private BackgroundWorker backgroundWorkerRefreshFromWeb = new
BackgroundWorker();
And in the constructor I set it up as follows.
backgroundWorkerRefreshFromWeb.WorkerReportsProgress = true;
backgroundWorkerRefreshFromWeb.WorkerSupportsCancellation = true;
backgroundWorkerRefreshFromWeb.DoWork +=
new DoWorkEventHandler(backgroundWorkerRefreshFromWeb_DoWork);
backgroundWorkerRefreshFromWeb.RunWorkerCompleted +=
new
RunWorkerCompletedEventHandler(backgroundWorkerRefreshFromWeb_RunWorkerCompleted);
backgroundWorkerRefreshFromWeb.ProgressChanged +=
new
ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
At the end of the constructor I call the following method to start it on
its way.
private void RefreshWebDataTimer(Object state)
{
if (!backgroundWorkerRefreshFromWeb.IsBusy &&
!backgroundWorkerLoadFromDB.IsBusy)
{
System.Diagnostics.Debug.Print("Refresh Timer Started at
{0}", DateTime.Now);
backgroundWorkerRefreshFromWeb.RunWorkerAsync(nfl);
}
}
The DoWork event handler calls a method from another project (DLL). That
method has a pattern which calls multiple threads to do process work. when
one of those threads throws an error, the application crashed and the
BackgroundWorker does not catch it in the RunWorkerCompleted event. The
pattern is a complex (probably overly complicated) but is as follows.
In the method the DoWork event handler calls I create a set of
"sub-worker" threads in a wrapper as follows...and then WAIT for all
threads to finish processing before moving on.
private static void GetRoster(Nfl teams, ref ManualResetEvent[] mre, ref
int index)
{
mre = new ManualResetEvent[Dictionary.NUMBER_OF_NFL_TEAMS];
ParseDataAsyncWrapper[] dw = new
ParseDataAsyncWrapper[Dictionary.NUMBER_OF_NFL_TEAMS];
index = 0;
foreach (NflTeam team in teams)
{
//Get Roster and create players
mre[index] = new ManualResetEvent(false);
dw[index] = new ParseDataAsyncWrapper(team, mre[index]);
ThreadPool.QueueUserWorkItem(new
WaitCallback(dw[index].RosterCallbackAsync),
index++);//Don't fully understand this
Thread.Sleep(wait.Next(Dictionary.THREAD_WAIT_MS));
}
foreach (ManualResetEvent re in mre) { if (re != null) { re.WaitOne();
} } //Wait for all threads to finish
mre = null; //allow to be disposed
dw = null;
}
I use the callback for each thread to get a webpage and then process that
page:
internal async void RosterCallbackAsync(object State)
{
if (Thread.CurrentThread.Name == null) { Thread.CurrentThread.Name =
string.Format("Roster{0}", State); }
WebPage = await
Html.WebClientRetryAsync(Dictionary.ROSTER_WEBPAGE.Replace(Dictionary.CITY_REPLACE_STR,
this.Team.CityAbr));
Html.ParseRoster(WebPage, Team);
DoneEvent.Set();
}
I am then throwing the exception in Html.ParseRoster but it is not getting
caught. This is on a different thread than the BackgroundWorker. I don't
know why the BackgroundWorker is not catching it. Since I am waiting for
all threads to finish before moving on I don't think the
RunWorkerCompleted event would run before I am done here.
I've looked at the help page for Application.DispatcherUnhandledException
event and it states:
you will need to write code to do the following: Handle exceptions on the
background thread. Dispatch those exceptions to the main UI thread.
Rethrow them on the main UI thread without handling them to allow
DispatcherUnhandledException to be raised.
My question is 1) Why is the excpetion not being caught? Should I use
Application.DispatcherUnhandledException and if so how can I accomplish
this? I would ultimately like to throw these exceptions to the
BackgroundWorker. Any suggestions or comments would be greatly
appreciated.
No comments:
Post a Comment