データベースから大量のデータを収集するバックグラウンドワーカーがあります。スレッドにタイムアウト制限を設定して、一定時間後に結果が返されない場合にプロセスがキャンセルされるようにします。
BackgroundWorker を開始すると同時に、メイン スレッドでタイマーを開始します。
意図的に BGW をスリープ状態にすると、タイマーが経過して .Elapsed イベントが呼び出されます。次に、バックグラウンド ワーカーをキャンセルしますが、完了させたい他のアクション (GUI のステータス バーを更新して MessageBox をスローする) を正常に完了しません。理由がわかりません、誰か助けてくれませんか?
タイムアウトとスリープは、テストのために意図的に設定されています。
/// <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);
}
}