System.Threading.Timer: Why is it hating me?

559 views Asked by At

I just started messing around with C#/.NET/mono and stuff, and I'm trying to make a simple song player. For this, I am using winmm.dll (did not find an easy cross-platform solution). The problem is this: I need to update a trackbar along with the song playing. I have two functions, Player.GetLength and Player.GetCurrentPosition, which return the time in miliseconds. If I call them "normally", everything is ok. But I need to call them in a timer, like this:

new System.Threading.Timer((state) =>
{
    length = Player.GetLength();
    pos = Player.GetCurrentPosition();
    trackBar1.Value = (pos / length) * 100;
}, null, 0, 100);     

This is GetLength, and GetCurrentPosition is similar:

public static int GetLength()
{
    StringBuilder s = new StringBuilder(128);
    mciSendString("status Song length", s, s.Capacity, IntPtr.Zero);
    return int.Parse(s.ToString());
}

The problem: when one of these two functions gets called, the program just stops, without any warning or exception thrown. Note: I am using .NET

So I was wondering if you can explain to me where I got it wrong :)

1

There are 1 answers

6
Chris Shain On BEST ANSWER

One thing I'd note is that System.Threading.Timer fires it's callback in it's own thread. Since you are interacting with the UI, you'd either want to use System.Windows.Forms.Timer (as a component on the form) or invoke back to the UI, as follows:

new System.Threading.Timer((state) =>
{
    length = Player.GetLength();
    pos = Player.GetCurrentPosition();
    trackBar1.Invoke(new Action(()=>trackBar1.Value = (pos / length) * 100));
}, null, 0, 100);   

Likewise, I am not sure if the Player class supports/tolerates multiple threads, but if not, there is the possibility that the whole callback needs to be invoked to the UI.