在后台线程中运行计时器

时间:2011-06-22 20:13:53

标签: c# background-thread

我正在寻找一种在后台程序线程中使用System.Windows.Forms.Timer的方法。我很难让它在后台线程中启动和停止。这就是我在做的事情:

private System.Windows.Forms.Timer chkTimer = new System.Windows.Forms.Timer();

然后在backgroundworker_dowork方法中我有这个:

     chkTimer.Interval = 2000;
     chkTimer.Tick += new EventHandler(chkTimer_Tick);
     chkTimer.Start();

在Tick方法中,我有与计时器相关的代码但由于某种原因它不会运行。如果我在ui线程中声明上述内容,则可行。请问someoine请帮我在后台线程中启动计时器吗?我不想使用System.Timers所以请不要建议

由于

7 个答案:

答案 0 :(得分:2)

Forms'计时器的工作原理是将消息发布到表单的句柄 - 消息,然后必须由表单的消息循环处理。后台线程(通常)没有消息循环,因此WM_Timer消息在发布时不会去任何地方(您的回调未被调用)。

使用System.Timers有什么问题?

答案 1 :(得分:2)

我不会完全使用计时器,这是额外的行李。从我读到的你想要有两个线程,UI和后台线程。

因此,让后台线程管理间隔而不是计时器。

Psuedo代码:

YourFileChecker checker = new YourFileChecker();
checker.CheckInterval = 60000; //milliseconds, the background thread will manage the interval

System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(checker.Check));
t.Start();

然后让Check方法执行以下操作:

 while(!_Stop)
 {
      //Do your work here

      //Wait the specified interval before checking again...
      Thread.Sleep(_CheckInterval);
 }

后台线程现在只是继续检查,直到它被告知(发出信号)停止。然后你根本不需要计时器,因为线程正在管理间隔。

答案 2 :(得分:2)

using System.Timers;
using System.Threading.Tasks;
.
.
.
var timer = new Timer(250);
.
.
.
private void Initialize()
{
    timer.Elapsed += (o, s) => Task.Factory.StartNew(() => OnTimerElapsed(o, s));
    timer.Start();
}
.
.
.
private void OnTimerElapsed(object o, ElapsedEventArgs s)
{
    //Do stuff
}

如果需要,您还可以删除OnTimerElapsed参数“o”和“s”。

答案 3 :(得分:1)

来自the documentation

  

Windows窗体计时器组件是单线程的,精度限制为55毫秒。如果需要更高精度的多线程计时器,请使用System.Timers命名空间中的Timer类。

System.Windows.Forms命名空间中的大多数组件都不是为在后台线程上运行而设计的。

答案 4 :(得分:1)

您应该只使用BackgroundWorker。 启用BackgroundWorker属性WorkerSupportsCancellation。在DoWork方法中添加:

while(!yourBGWorker.CancelationPending)
{
   //Do some work
   Thread.Sleep(2000);
}

它做你想做的事 - 在后台线程中做一些工作并等待指定的时间段。您也可以在致电yourBGWorker.CancelAsync();

后取消进度

答案 5 :(得分:0)

System.Windows.Forms.Timer完全基于Win32消息,因此需要消息循环。换句话说,它只能在UI线程上运行。另一种选择是System.Threading.Timer,它将在一个单独的线程中打勾,但你提到它不适合你。据我所知,没有办法创建一个将调度到任意线程的计时器(但你可以自己调度)。从技术上讲,可以在你的线程中启动第二个消息循环并在那里运行Windows Forms计时器,但我不推荐它(你需要抽取消息等)。通常有更好的方法来做到这一点。

答案 6 :(得分:0)

我最近写了一篇文章,可能就是你想要的。它在c#中演示了一个通用的轮询组件,它以指定的时间间隔运行,并使用后台线程来执行指定的用户操作。您可以在主线程上启动它以在工作线程上运行事件。

样本用法:

IPoller poller = new UrlPoller(args[0], TimeSpan.FromSeconds(7));
IPolling pollingComponent = new Polling.Core.Polling(poller);
pollingComponent.SubscribeForPollingUpdates(PollingAction);
pollingComponent.Start();

代码和完整用法:

http://www.avantprime.com/blog/24/an-example-of-repeating-code-using-a-worker-thread-without-using-timers-c