我有一个很棒的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
}
答案 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了解我的解决方案。