2

我正在寻找一种在后台线程中使用 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 线程中声明上述内容,它可以工作。有人可以帮我在后台线程中启动计时器吗?我不想使用 System.Timers 所以请不要建议

谢谢

4

7 回答 7

3
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”。

于 2013-01-04T22:44:50.887 回答
2

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

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

伪代码:

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);
 }

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

于 2011-06-22T21:44:56.533 回答
2

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

使用 System.Timers 有什么问题?

于 2011-06-22T20:18:18.490 回答
1

文档中

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

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

于 2011-06-22T20:18:23.057 回答
1

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

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

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

于 2011-06-22T20:27:59.137 回答
0

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

于 2011-06-22T20:18:22.023 回答
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

于 2012-09-14T15:53:49.957 回答