2009-11-11 93 views
0

我有一个Silverlight 3应用程序,它的效果很好,除了4台机器。 DispatcherTimer和Storyboards在这4台机器上并不一致。我已经创建了一个非常简单的测试应用程序来试图解决这个问题,我将列出下面的代码。Silverlight 1秒DispatcherTimer只在某些机器上每隔30秒发射一次

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

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

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 

    } 
+0

更多疑难解答。我在其中一个盒子上安装了Firefox和Chrome,并获得了相同的效果。但每隔一段时间,我就会看到一个5到10秒的运行,它开始正确运行 - TextBlocks每秒更新一次。 5或10秒后,它会回到30秒延迟。 有趣的是,如果你打开所有三个浏览器(IE,FF,Chrome),他们都会一致地做到这一点。也许盒子上某处存在瓶颈。 我不确定从哪里开始排除故障。 IT将禁用MacAfee,我们会看到是否有帮助。 – 2009-11-11 20:18:53

回答

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毫秒,而不是仅用于测试一秒。

+0

感谢科比。这没有帮助,但它看起来像我应该使用BeginInvoke无论如何。 – 2009-11-11 19:55:38

0

我不知道为什么会发生这种情况,但我现在肯定这不是代码问题。

如果我积极与工作站进行交互,一切都会很好。打开浏览器,复制文件等。但是,如果工作站处于空闲状态 - 只需运行Silverlight测试应用程序,就可以快速返回到耗时30秒来启动计时器。

我已经验证了这种情况不仅与我的应用程序,和我的测试应用程序,也可以与其他Silverlight应用程序喜欢这里的演示: http://wpierdalaj.pl/SWG/SilverlightCountDown/Run/SilverlightCountDownTimerExampleTestPage.html

对于我创建了一个批处理文件变通方法,拷贝100MB文件,删除它,然后重新开始。只要这个批处理文件运行一切都很好。 :)

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

0

我写了一个简单的使用任务的扩展方法。您可以更改主要的DelayInvoke方法以使用DispatcherTimer。

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

+0

如果链接失效,您能否在答案本身中总结您的解决方案? – jonsca 2012-12-18 00:48:24