views:

80

answers:

3

hello,

I have a kinda awkward problem, I'm working with C# and WPF in .NET 4.0 and what I need is a timer that will create only one thread but it will need to work in the background, so not in the main thread, the problem is using System.Windows.Forms.Timer or DispatchTimer will automatically force it to work on the main thread and be influenced by the UI, on the other side using System.Timers.Timer or System.Threading.Timer will create a new thread for every cycle that overpasses the time interval, this will happen since the code in the elapsed timer event is a bit big, although part of it is sent further to a background worker.

so I was thinking if it's possible to force, say the System.Timers.Timer, to work in the background and never spawn to more then one thread, also I am opened to other suggestions

+1  A: 

Just use a System.Threading.Timer with a period of 0 so that the callback runs only once. When everything is done, recharge the timer so it will fire again later. You'll have guaranteed only ever one thread running this way.

Hans Passant
A: 

Use System.Timers.Timer, which fires its elapsed event handler on a ThreadPool thread. As soon as you enter the event handler, stop the timer. At the end of your event handler, start the timer and it will start counting down from the beginning of its interval.

Here's a simple example with a 100ms timer that spends 2 seconds in it's elapsed event handler:

static void Main(string[] args)
{
    System.Timers.Timer myTimer = new System.Timers.Timer(100);
    myTimer.Elapsed += new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
    myTimer.Start();
    Console.ReadLine();
}

static void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    ((System.Timers.Timer)sender).Stop();
    Console.WriteLine(DateTime.Now.ToString("HH.mm.ss"));
    System.Threading.Thread.Sleep(2000);
    ((System.Timers.Timer)sender).Start();
}
ebpower
yes, thank you, that seems the easiest way to get what I need
WarBorg
A: 

DispatcherTimer has a constructor overload that lets you do exactly what you want. Use it in the context of your thread:

using System.Threading;
using WpfThreading = System.Windows.Threading;

...

Thread t = new Thread(() => 
{
    var interval = TimeSpan.FromSeconds(3.0);
    var priority = WpfThreading.DispatcherPriority.Background;
    EventHandler callback = (a, e) => { };
    var dispatcher = WpfThreading.Dispatcher.CurrentDispatcher; // dispatcher for this thread
    WpfThreading.DispatcherTimer dt = new WpfThreading.DispatcherTimer(interval, priority, callback, dispatcher);

    bool sameDispatchers = WpfThreading.Dispatcher.CurrentDispatcher == this.Dispatcher; // false
});
t.Start();
Grozz