【问题标题】:Call BackgroundWorker RunWorkerCompleted event when timer stops定时器停止时调用 BackgroundWorker RunWorkerCompleted 事件
【发布时间】:2012-01-30 11:40:26
【问题描述】:

我有一个BackgroundWorker,它创建了一个计时器。计时器重复调用DataTable。我只希望在计时器停止时调用BackgroundWorker.RunWorkerCompleted 事件。我该怎么做?

谢谢。

【问题讨论】:

    标签: c# timer backgroundworker


    【解决方案1】:

    只需在BackgroundWorkerDoWork 事件处理程序中创建一个循环并重复循环直到计时器停止。或多或少是这样的:

    var worker = new BackgroundWorker();
    worker.DoWork += (sender, e) =>
    {
        var timer = new Timer();
        timer.Elapsed += (s, _e) =>
        {
           // call the database
        };
    
        timer.Start();
    
        while (timer.Enabled)
        {
            // at some point: timer.Stop();
        } 
    
        // if we are here, timer is no longer Enabled
        // RunWorkerCompleted event will be fired next
    };
    

    (显然我忽略了设置计时器的Interval 等)

    【讨论】:

    • 如果定时器是在事件内部定义的,你怎么能禁用它(这样你就没有从外部对定时器的引用)?
    • @ZombieHunter 计时器可以在Elapsed 事件处理程序中禁用自身,例如基于从它进行的数据库调用中检索到的数据(或缺少数据)。但这是一个有效的观点;当然,如果您需要从外部访问计时器,则应在其他地方声明计时器。此外,lambdas 并不总是最好的选择。我的代码只是一个 sn-p,旨在提供一个想法的图片。
    【解决方案2】:

    BackGroundWorker.RunWorkerCompleted 在您的 DoWork 事件完成后调用。因此,如果您确保 DoWork 事件完成,您的 RunWorkerCompleted 事件应该由后台工作人员调用。

    另一种解决方案是在后台工作人员之外创建计时器,并通过计时器控制后台工作人员实例。在计时器事件中,检查 IsBusy 属性是否设置为 false 并启动后台工作程序,如果 IsBusy 为 true,则跳过。

    示例:

    _worker.DoWork += (sender, e) =>
    {   
        BackgroundWorker worker = sender as BackgroundWorker;
    
        // Do your database stuff
    
        e.Result = databaseResult;
    }
    
    _timer.Elapsed += (source, e) =>
    {
        if(!_worker.IsBusy)
        {
            _worker.RunWorkerAsync();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-31
      • 1970-01-01
      相关资源
      最近更新 更多