可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Im looking for a way to use a System.Windows.Forms.Timer within a backgrounder thread. I cam having a lot of trouble getting it to start and stop within the background thread. This is what i am doing:
private System.Windows.Forms.Timer chkTimer = new System.Windows.Forms.Timer();
Then in the backgroundworker_dowork method i have this:
chkTimer.Interval = 2000;
chkTimer.Tick += new EventHandler(chkTimer_Tick);
chkTimer.Start();
In the Tick method i have the timer related code but it will not run for some reason. If i declare the above in the ui thread, it works. Can someoine please help me start the timer within the background thread? I do not want to use System.Timers so please dont suggest that
Thanks
回答1:
Forms' timer works by posting messages to the form's handle - messages, which must then be processed by the form's message loop. Background threads (usually) don't have message loops so the WM_Timer message, while being posted, doesn't go anywhere (your callback isn't being invoked).
What's wrong with using System.Timers?
回答2:
I would not use a timer altogether, its extra baggage. From what I read you want to have two threads, the UI and the background thread.
So, have the background thread manage the interval instead of the timer.
Psuedo Code:
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();
Then have the Check method do something like this:
while(!_Stop)
{
//Do your work here
//Wait the specified interval before checking again...
Thread.Sleep(_CheckInterval);
}
The background thread now just keeps checking until it is told (signaled) to stop. Then you don't need the timer at all because the thread is managing the interval.
回答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
}
You can also get rid of the OnTimerElapsed parameters "o" and "s" if you want.
回答4:
From the documentation:
The Windows Forms Timer component is single-threaded, and is limited to an accuracy of 55 milliseconds. If you require a multithreaded timer with greater accuracy, use the Timer class in the System.Timers namespace.
Most components in the System.Windows.Forms
namespace are not designed to run on background threads.
回答5:
You should use just BackgroundWorker
.
Enable the BackgroundWorker
property WorkerSupportsCancellation
. In the DoWork
method add:
while(!yourBGWorker.CancelationPending)
{
//Do some work
Thread.Sleep(2000);
}
It does what you want - do some work in background thread and wait for a specified time period. Also you can cancel progress after calling yourBGWorker.CancelAsync();
回答6:
System.Windows.Forms.Timer is based entirely on Win32 messages and as such requires a message loop. In other words, it can only run on the UI thread. An alternative is System.Threading.Timer, which will tick in a separate thread but you mention it won't work for you. As far as I know, there is no way to create a timer that will dispatch to an arbitrary thread (you can do the dispatching yourself however). Technically, it is possible to start a second message loop in your thread and run a Windows Forms timer there but I would not recommend it (you need to pump messages, etc). Usually there's a better way to do this.
回答7:
I have recently written an article that may be just what you are looking for. It demonstrates in c# a generic polling component that runs at a specified interval and uses a background thread to perform the user action specified. You can launch this on your main thread to run the event on a worker thread.
Sample usage:
IPoller poller = new UrlPoller(args[0], TimeSpan.FromSeconds(7));
IPolling pollingComponent = new Polling.Core.Polling(poller);
pollingComponent.SubscribeForPollingUpdates(PollingAction);
pollingComponent.Start();
For the code and complete usage:
http://www.avantprime.com/blog/24/an-example-of-repeating-code-using-a-worker-thread-without-using-timers-c