Timer Elapsed Event不执行所有操作

时间:2013-01-24 22:24:39

标签: c# wpf multithreading timer backgroundworker

我有一个Backgroundworker,它从数据库中收集大量数据。我想在线程上设置超时限制,这样如果在一段时间后它没有返回结果,则取消该过程。

我在启动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);
            }
        }

1 个答案:

答案 0 :(得分:2)

当您尝试从另一个线程更新GUI时,我假设您的cancelTimer_Elapsed方法会无声地崩溃。如果没有调试Visual Studio设置为中断所有异常,有时很难找到后台线程中抛出的异常 - 您可以在菜单Debug > Exceptions中设置并检查所有CLR异常。或者,您可以将方法体包装在try块中,并将断点放在catch块中。

void cancelTimer_Elapsed(object sender, ElapsedEventArgs e)
{
   try
   {
        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;
    }
    catch(Exception ex)
    {
        int breakpoint = 42;
    }
}

我不确定是这种情况,但在我看来值得一试。