BackgroundWorker暂停

时间:2013-01-10 13:19:28

标签: c# visual-studio-2010 timer thread-safety backgroundworker

我有BackgroundWorker _worker

void _worker_DoWork(object sender, DoWorkEventArgs e)
{
    _timer = new System.Timers.Timer();
    _timer.Elapsed += new System.Timers.ElapsedEventHandler(_timer_Elapsed);
    _timer.Interval = 5000;
    _timer.Start();
}

当它到达_timer.Start()行时,它认为它已经完成,因此触发RunWorkerCompleted event

我不希望它在达到_timer.Interval时间并且_timer Elapsed event被触发之前完成:

void _timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    for (int i = 1; i < 20; i++)
    {
        if (listBox1.InvokeRequired)
            listBox1.Invoke((Action)(() => listBox1.Items.Add("Do Things Thread")));
        else
            listBox1.Items.Add("Do Things Completed");

        _worker.ReportProgress((int)(((decimal)i / (decimal)20) * 100));

        Thread.Sleep(1000);
    }

    _timer.Stop();
}

因为我需要BackgroundWorker报告一些进展。

我该怎么做我需要它在不同的thread上运行。

3 个答案:

答案 0 :(得分:1)

总结讨论和解决方案。

除非您提供同步对象,否则System.Timers.Timer将自动为您调度计时器事件,如MSDN中所述:

  

如果SynchronizingObject属性为null,则Elapsed事件为   在ThreadPool线程上引发。如果处理了Elapsed事件   持续时间超过Interval,事件可能会再次提升   ThreadPool线程。在这种情况下,事件处理程序应该是   折返。

这意味着后台工作者变成了超级流行音乐。你可以简单地让你的计时器事件代码运行(因为它使用invoke无论如何都与UI交互)。

这确实意味着如果这些事件需要很长时间,它们可以同时运行。但是,您当然可以在事件回调中停止并启动计时器。

答案 1 :(得分:0)

您的_timer_Elapsed事件位于其他线程上。一旦控制流通过_worker_DoWork函数,计时器的实例就会过期。您的计时器对象变量的范围仅限于该函数,因此它不会以这种方式工作。

我建议你把Thread.sleep(5000)放在timer _worker_dowork函数本身。它不会影响你的应用程序,因为线程会休眠,gui仍然会响应。

答案 2 :(得分:0)

我认为,只是通过玩弄我所做的,是我调用了进度条,所以我不需要ReportProgress:

_worker.ReportProgress((int)(((decimal)i / (decimal)20) * 100));

更改为:

if (progressBar1.InvokeRequired)
    progressBar1.Invoke((Action)(() => progressBar1.Value = (int)(((decimal)i / (decimal)20) * 100)));
else
    progressBar1.Value = (int)(((decimal)i / (decimal)20) * 100);

这意味着,我不必暂停BackgroundWorker,并且计时器是在另一个线程上调用的,并且会一直处理掉,直到被处理掉。