我正在寻找一种在后台程序线程中使用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所以请不要建议
由于
答案 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)
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();
代码和完整用法: