views:

408

answers:

2

I've got a Silverlight 3 app that works great, except on 4 machines. DispatcherTimer and Storyboards are not firing consistently on these 4 machines. I've created a very simple test app to try to figure this out, I'll list the code below.

Basically the test app updates two TextBlocks every second. One using DispatcherTimer, one using a Storyboard Animation. This works great - the text boxes update "1, 2, 3..." every second. But on the 4 affected machines the TextBlocks don't update every second, they update between 27 and 33 seconds. The DispatcherTimer and Storyboard updates are done at the exact same time.

CPU, Memory, HD are all fine. Task Manager and SilverlightSpy shows that everything this is fine. These are all 3 Ghz workstations with 3GB of RAM with nothing else running on them.

XAML:

    <TextBlock Text="0" Name="DispatcherTimerText" Grid.Column="0" />
    <TextBlock Text="0" Name="SBLoopTimerText" Grid.Column="1" />

C#:

        Storyboard _sbLoop = new Storyboard();

    public MainPage()
    {
        InitializeComponent();

        Storyboard_Start();
        Timer_Start();

    }

    void Timer_Start()
    {
        System.Windows.Threading.DispatcherTimer dt1 = new System.Windows.Threading.DispatcherTimer();
        dt1.Interval = new TimeSpan(0, 0, 1);  // 1 second
        dt1.Tick += new EventHandler(Timer_Tick);
        dt1.Start();
    }
    void Timer_Tick(object sender, EventArgs e)
    {
        TextBlock txt = ((TextBlock)LayoutRoot.Children.Single(t => ((TextBlock)t).Name == "DispatcherTimerText"));
        txt.Text = (int.Parse(txt.Text) + 1).ToString();
    }

    void Storyboard_Start()
    {
        _sbLoop.Duration = TimeSpan.FromSeconds(1);
        _sbLoop.Completed += new EventHandler(StoryboardLoop);
        _sbLoop.Begin();
    }

    void StoryboardLoop(object sender, EventArgs e)
    {
        TextBlock txt = ((TextBlock)LayoutRoot.Children.Single(t => ((TextBlock)t).Name == "SBLoopTimerText"));
        txt.Text = (int.Parse(txt.Text) + 1).ToString();

        _sbLoop.Begin();    // Restart sb animation

    }
A: 

Just a guess, but it could be the fact that you're trying to update the UI directly in the events. I'd be curious to see if this code would work better for you and fix the problem on the machines that don't work.

public partial class MainPage : UserControl
{
    Storyboard _sbLoop = new Storyboard();
    private int _slCounter = 0;
    private int _tmrCounter = 0;
    private TimeSpan interval = TimeSpan.FromMilliseconds(100);

    public MainPage()   
    {
        InitializeComponent();
        Storyboard_Start();
        Timer_Start();
    }

    void Timer_Start()
    {
        System.Windows.Threading.DispatcherTimer dt1 = new System.Windows.Threading.DispatcherTimer();
        dt1.Interval = interval;
        // 1 second
        dt1.Tick += new EventHandler(Timer_Tick);
        dt1.Start();
    }

    void Timer_Tick(object sender, EventArgs e)
    {
        _tmrCounter++;
        Dispatcher.BeginInvoke(() => DispatcherTimerText.Text = _tmrCounter.ToString());
    }

    void Storyboard_Start()
    {
        _sbLoop.Duration = interval;
        _sbLoop.Completed += new EventHandler(StoryboardLoop);
        _sbLoop.Begin();
    }

    void StoryboardLoop(object sender, EventArgs e)
    {
        _slCounter++;
        Dispatcher.BeginInvoke(() => SBLoopTimerText.Text = _slCounter.ToString());
        _sbLoop.Begin();
        // Restart sb animation
    }
}

This code uses BeginInvoke to update the UI instead of directly updating it. You might need to change my interval since I put it as 100 ms instead of one second just for testing.

Bryant
Thanks Bryant. That didn't help but it does look like I should be using BeginInvoke anyway.
Bradley Dean
A: 

I'm not sure why this is happening, but I'm now positive this isn't a code issue.

Everything works great if I'm actively interacting with the workstation. Opening browsers, copying files, etc. But if the workstation is sitting idle - just running the Silverlight test app, it quickly goes back to taking 30 seconds to fire the timers.

I've verified this happens not only with my app, and my test app, but also with other Silverlight apps like the demos here: http://wpierdalaj.pl/SWG/SilverlightCountDown/Run/SilverlightCountDownTimerExampleTestPage.html

For a workaround I created a batch file that copies a 100MB file, deletes it, and then starts over. As long as this batch file is running everything works great. :)

For a long term solution IT is going to figure out why these workstations go to "sleep" so quickly.

Bradley Dean