Silverlight 1秒DispatcherTimer仅在某些机器上每30秒左右触发一次

时间:2009-11-11 18:04:15

标签: silverlight silverlight-3.0

我有一个很棒的Silverlight 3应用程序,除了4台机器。 DispatcherTimer和Storyboard在这4台机器上没有持续触发。我已经创建了一个非常简单的测试应用程序来试图解决这个问题,我将列出下面的代码。

基本上,测试应用每秒更新两个TextBlock。一个使用DispatcherTimer,一个使用Storyboard Animation。这很好用 - 文本框每秒更新“1,2,3 ......”。但是在4台受影响的机器上,TextBlocks不会每秒更新,它们会在27到33秒之间更新。 DispatcherTimer和Storyboard更新完全在同一时间完成。

CPU,内存,高清都很好。任务管理器和SilverlightSpy显示一切都很好。这些都是3 Ghz工作站,带有3GB内存,没有其他任何东西在运行。

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

    }

3 个答案:

答案 0 :(得分:0)

只是一个猜测,但可能是您尝试直接在事件中更新UI。我很想知道这段代码是否能更好地为你工作,并在不起作用的机器上修复问题。

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
    }
}

此代码使用BeginInvoke更新UI,而不是直接更新它。您可能需要更改我的间隔,因为我将其设置为100毫秒而不是一秒钟仅用于测试。

答案 1 :(得分:0)

我不确定为什么会这样,但我现在肯定这不是代码问题。

如果我正在积极地与工作站进行交互,那么一切都很有效。打开浏览器,复制文件等。但是如果工作站处于空闲状态 - 只需运行Silverlight测试应用程序,它就会很快恢复30秒钟来启动计时器。

我已经验证了这不仅适用于我的应用和我的测试应用,还有其他Silverlight应用,例如这里的演示: http://wpierdalaj.pl/SWG/SilverlightCountDown/Run/SilverlightCountDownTimerExampleTestPage.html

为了解决方法,我创建了一个批处理文件,用于复制100MB文件,删除它,然后重新开始。只要这个批处理文件正在运行,一切都很好。 :)

对于长期解决方案,IT部门将弄清楚为什么这些工作站会如此快速地“睡眠”。

答案 2 :(得分:0)

我写了一个使用Task的简单扩展方法。非常欢迎您更改主要的DelayInvoke方法以使用DispatcherTimer。

请参阅This Post了解我的解决方案。