rosa.tarraga
rosa.tarraga

Reputation: 165

DispatcherTimer in a new thread

I'm developing a c# application. I need 2 threads; the main one, and another that is continuously looking for information through my database. I want to use Dispatcher Timer as:

dispatcherBd.Tick += (s,e) => CallPoll (s,e);
dispatcherBd.Interval = new TimeSpan(0,0,0,100);
dispatcherBd.Start();

If i do this into my main thread, everything works perfectly, but if I do into a new thread. It doesn't work.

public Main(){
    threadDB = new Thread(InitDispatcher);
    threadDB.Start();
}

private void InitDispatcher(){
    DispatcherTimer dispatcherBd.Tick += (s,e) => CallPoll (s,e);
    dispatcherBd.Interval = new TimeSpan(0,0,0,100);
    dispatcherBd.Start();
}

What's the problem?

Upvotes: 1

Views: 3850

Answers (2)

Zazaeil
Zazaeil

Reputation: 4119

Forget about manual threading unless absolutely necessary. Use Task.Run as a way to schedule your (possible, continuous) job on another thread. Don't forget about Dispatcher.Invoke proxy if you need to update your UI from newly created (non-UI) thread.

In case things are getting too complicated, consider Reactive Extensions. There exists timer out of the box and many, many more.

Upvotes: 0

René Vogt
René Vogt

Reputation: 43896

As you stated in the comments, you declare dispatcherBd as a local variable inside InitDispatcher():

private void InitDispatcher()
{
    DispatcherTimer dispatcherBd = new DispatcherTimer();
    // ...

So dispatcherBd is only in scope inside InitDispatcher and will be availabe for garbage collection as soon as the method is left.
When it gets garbage collected and finalized, the timer event will no longer be raised.

So try changing dispatcherBd to a field instead:

private DispatcherTimer dispatcherBd;

private void InitDispatcher()
{
    dispatcherBd = new DispatcherTimer();
    // ...

But note that DispatcherTimer invokes its handler on the UI thread. So if CallPoll takes a lot of time, your UI will be blocked.
So you might want to start another thread from the timer's handler:

dispatcherBd.Tick += (s, e) => { Task.Run(() => CallPoll(s, e)) };

or use a System.Threading.Timer instead of a DispatcherTimer. That one runs the Tick event on a thread pool thread.

In both cases you need to get back to the UI thread when you want to display the results on your UI.

Upvotes: 1

Related Questions