在过去的几天里,我一直在研究 DispatcherTimer,但我仍然无法理解一些东西。以下是我目前所了解的,
- tick 事件不会同时发生两次link
- 无需担心对象的所有者线程,因为调度程序计时器会自动执行 UI 线程中的所有工作
- 滴答的时间可能不是很准确,因为滴答本质上是从队列中执行的
现在我不清楚的是如果有另一个事件在滴答事件之间运行,则执行代码的顺序。我有一个测试 WPF 应用程序,它使用一个 DispatcherTimer,其滴答事件执行 2 个功能。firstStep()
并按secondStep()
顺序。
将firstStep()
变量设置为null
同时secondStep()
将其设置为非空值。设置值后, secondStep() 将启动一个包含 Completed 事件的故事板,该事件尝试访问此变量。
所以我的问题是,如果我们保持计时器运行,那么 Completed 事件是否可能介于firstStep()
and函数之间?secondStep()
我编写了一个测试应用程序,似乎就是这种情况,最终我们将达到一个状态,即当 Completed 事件被执行时变量为空。但是我不明白这是怎么发生的,因为firstStep()
并按secondStep()
顺序执行,所以在这两个函数之间应该不可能执行 Completed 事件(或者我在这里错了)。UI 线程是否并行执行 tick 和 Completed 事件?
有人可以详细解释一下 UI 线程是如何按顺序执行事件的,例如示例的故事板完成事件和 dispatcherTimer 的滴答声?感谢您的阅读,非常感谢您的评论,我正在努力解决这个问题。以下是我使用的测试代码,运行一段时间后最终会报错。
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
storyBoardTest = new Storyboard();
storyBoardTest.Completed += new EventHandler(storyBoardTest_Completed);
DoubleAnimation animation = new DoubleAnimation(1, 0.9, new Duration(TimeSpan.FromSeconds(1)));
Storyboard.SetTarget(animation, this);
Storyboard.SetTargetProperty(animation, new PropertyPath(UIElement.OpacityProperty));
storyBoardTest.Children.Add(animation);
DispatcherTimer dt = new DispatcherTimer();
dt.Interval = TimeSpan.FromMilliseconds(500);
dt.Tick += new EventHandler(dt_Tick);
dt.Start();
}
private Window windowTest = null;
private Storyboard storyBoardTest = null;
void dt_Tick(object sender, EventArgs e)
{
firstStep();
secondStep();
}
private void firstStep()
{
windowTest = null;
}
private void secondStep()
{
windowTest = this;
storyBoardTest.Stop();
storyBoardTest.Begin(this);
}
void storyBoardTest_Completed(object sender, EventArgs e)
{
//Attempt to access object throws null error. Why?
windowTest.Title = "test";
windowTest = null;
}
}
调用栈:
WpfApplication1.exe!WpfApplication1.Window1.storyBoardTest_Completed(object sender = {System.Windows.Media.Animation.ClockGroup}, System.EventArgs e = null) 第 63 行 C# PresentationCore.dll!System.Windows.Media.Animation.Clock.FireEvent (System.Windows.EventPrivateKey 键) + 0x5b 字节
PresentationCore.dll!System.Windows.Media.Animation.Clock.RaiseAccumulatedEvents() + 0x160 字节
PresentationCore.dll!System.Windows.Media.Animation.TimeManager.RaiseEnqueuedEvents() + 0x60字节
PresentationCore.dll!System.Windows.Media.Animation.TimeManager.Tick() + 0x28a 字节
PresentationCore.dll!System.Windows.Media.MediaContext.RenderMessageHandlerCore(object resizedCompositionTarget) + 0xbc 字节
PresentationCore.dll!System.Windows.Media.MediaContext.AnimatedRenderMessageHandler(object resizedCompositionTarget) + 0x9d 字节