【发布时间】:2018-04-23 23:40:34
【问题描述】:
我相信我在此代码示例中存在竞争条件,但不确定如何缓解它。
我的情况是 XAsync() 总是在 UI 线程上运行。在 XAsync() 中,我设置了 m_importantMemberVariable,然后启动了一个计时器;在计时器触发之前有 1 秒的延迟。
我担心的是计时器的滴答事件会调用 m_importantMemberVariable 上的方法。但是,在启动计时器和触发 Tick 之间的 1 秒间隔内,可以再次调用 XAsync() 并覆盖 m_importantMemberVariable。
代码示例:
task<void> BobViewModel::XAsync()
{
return create_task(CreateSomethingAsync())
.then([this](SomethingAsync^ aThing)
{
this->m_importantMemberVariable = aThing;
OnPropertyChanged("ImportantMemberVariable");
// Timer has 1 second delay.
this->m_myDispatcherTimer->Start();
}, task_continuation_context::use_current())
.then([activity](task<void> result)
{
// more continuations...
});
}
void BobViewModel::OnTimerTick(Object^, Object^)
{
// Stopping the timer and detaching the event handler
// so timer only fires once.
m_myDispatcherTimer->Stop();
m_myDispatcherTimer->Tick -= m_impressionTimerToken;
m_myDispatcherTimer = { 0 };
// * Possible race condition *
m_importantMemberVariable->DoImportantThing();
}
问题:假设我对竞争条件的看法是正确的,有没有办法缓解它?
我的理解是,tick 事件会在 UI 线程上触发,因此同步原语将无济于事(因为 UI 线程已经拥有访问权限)。
【问题讨论】:
-
没有种族。唯一可能出错的是 DoImportantThing() 将在更新 m_importantMemberVariable 后不到 1 秒内被调用。代码在调用 Start() 之前忘记了 Stop() 计时器。
-
@HansPassant - 如果 XAsync 的第二个调用者在计时器启动后(但在触发滴答事件之前)使 m_importantMemberVariable 为空,那怎么不会产生空引用异常?你是说这不可能发生吗?如果有,为什么?
-
如果您遵循建议,则您已停止计时器。当变量为空时,为什么要再次调用 Start()?
-
这似乎是对你已经问过两次我回答的问题的欺骗。
-
@PeterTorr-MSFT - 不同之处在于这个问题将 DispatcherTimer 混入其中,因此它不仅限于任务延续。
标签: multithreading uwp task uwp-xaml