I have a Backgroundworker which collects a large amount of data from a database. I want to set a timeout limit on the thread so that if it does not return the results after a set amount of time the process is cancelled.
I start a timer on the main thread at the same time as I start the BackgroundWorker.
If I purposely make the BGW sleep, the timer elapses and calls the .Elapsed event. It then cancels the Background worker, however it does not successfully complete the other actions I want it to complete, which are update the status bar on the GUI and throw up MessageBox. I don't understand why not, can anyone help?
Time out and sleep are purposely set for testing.
/// <summary>
/// loads Assets by group ID
/// Populates Grid on asset listing page
/// </summary>
/// <param name="groupId"></param>
/// <param name="user"></param>
internal void PopulateGridAssetsByGroup(int groupId, User user)
{
//update statusbar
AfMainWindow.MainWindow.UpdateStatusBar("Loading Assets...");
//setup BG worker
populateGridAssetsWorker = new BackgroundWorker {WorkerSupportsCancellation = true, WorkerReportsProgress = false};
populateGridAssetsWorker.DoWork += populateGridAssetsWorker_DoWork;
populateGridAssetsWorker.RunWorkerCompleted += populateGridAssetsWorker_RunWorkerCompleted;
//setup timer which will cancel the background worker if it runs too long
cancelTimer = new Timer {Interval = 2000, Enabled = true, AutoReset = false};
cancelTimer.Elapsed += cancelTimer_Elapsed;
cancelTimer.Start();
populateGridAssetsWorker.RunWorkerAsync(groupId); //start bg worker
}
void cancelTimer_Elapsed(object sender, ElapsedEventArgs e)
{
populateGridAssetsWorker.CancelAsync();
cancelTimer.Stop();
AfMainWindow.MainWindow.UpdateStatusBar("Could not load assets, timeout error");
MessageBox.Show("Operation Timed Out\n\nThe Server did not respond quick enough, please try again",
"Timeout", MessageBoxButton.OK, MessageBoxImage.Exclamation, MessageBoxResult.OK);
AfMainWindow.MainWindow.Busy.IsBusy = false;
}
/// <summary>
/// when bg worker complete, update the AssetGrid on Asset Listing Page with results
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void populateGridAssetsWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
cancelTimer.Stop();
//my thread complete processing
}
/// <summary>
/// Perform the DB query and collect results for asset listing
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void populateGridAssetsWorker_DoWork(object sender, DoWorkEventArgs e)
{
var assetListByGroup = new List<AssetLinked>();
Thread.Sleep(5000);
if (populateGridAssetsWorker.CancellationPending)
{
return;
}
try
{
//My SQL actions
if (populateGridAssetsWorker.CancellationPending)
{
return;
}
}
catch (Exception ex)
{
Globals.AFWideSettings.GeneralErrorMessage(ex.Message);
}
}