在我的代码中,我订阅了一个在不同线程上发生的事件。每次发生此事件时,我都会收到一个发布到可观察集合的字符串:
Dispatcher currentDispatcher = Dispatcher.CurrentDispatcher;
var SerialLog = new ObservableCollection<string>();
private void hitStation_RawCommandSent(object sender, StringEventArgs e)
{
string command = e.Value.Replace("\r\n", "");
Action dispatchAction = () => SerialLog.Add(command);
currentDispatcher.BeginInvoke(dispatchAction, DispatcherPriority.Render);
}
下面的代码在我的视图模型中(可能在后面的代码中,在这种情况下无关紧要)。当我调用“hitstation.PrepareHit”时,上面的事件会被调用几次,然后我等待并调用“hitStation.HitBall”,上面的事件再被调用几次。
private void HitBall()
{
try
{
try
{
Mouse.OverrideCursor = Cursors.Wait;
//prepare hit
hitStation.PrepareHit(hitSpeed);
Thread.Wait(1000);
PlayWarning();
//hit
hitStation.HitBall(hitSpeed);
}
catch (TimeoutException ex)
{
MessageBox.Show("Timeout hitting ball: " + ex.Message);
}
}
finally
{
Mouse.OverrideCursor = null;
}
}
我遇到的问题是绑定到我的SerialLog的ListBox只有在HitBall方法完成时才会更新。我期待从PrepareHit看到一堆更新,暂停,然后从HitBall获得更多更新。
我尝试了几个DispatcherPriority参数,但它们似乎没有任何效果。
答案 0 :(得分:4)
我认为你是在封锁自己。
UI Thread在Thread.Wait上等待,BeginInvoke将动作发送到dipatcher,但是UI Thread正忙着等待。这就是为什么UI更新只在HitBall完成之后完成,也就是说,当UI线程完成处理时。
要解决这个问题,你应该在另一个线程中启动HitBall方法的代码,释放UI:
private void HitBall()
{
try {
Mouse.OverrideCursor = Cursors.Wait;
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
Action hitOperations = () =>
{
hitStation.PrepareHit(hitSpeed);
Thread.Wait(1000);
//Only needed if PlayWarning needs access to UI Thread
dispatcher.Invoke(() => PlayWarning());
hitStation.HitBall(hitSpeed);
dispatcher.Invoke(() => Mouse.OverrideCursor = null);
};
//Free the UI from work, start operations in a background thread
hitOperations.BeginInvoke(null, null);
}
catch (TimeoutException ex)
{
MessageBox.Show("Timeout hitting ball: " + ex.Message);
}
}
此外,如果Thread.Wait(1000)的预期用途是等待事件刷新UI,则不再需要此实现。
答案 1 :(得分:1)
是否需要在ViewModel上引发PropertyChanged事件这么简单?
答案 2 :(得分:0)
除非有上下文切换,否则您可能看不到来自PrepareHit
的更新,并且无法保证何时会发生上下文切换(除非您阻止当前线程并且这会增加上下文切换发生的可能性) )。
正如iCe所提到的,如果你在UI线程上这样做,那么你可能会阻止你的UI。当您致电Thread.Wait
时,您的用户界面会阻止/冻结吗?如果没有,则继续阅读以下内容:
<强>更新强>
我想不出任何不会影响并发性的事情......如果不妥协并发性,你可以尝试提高BeginInvoke
的优先级:http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherpriority.aspx
currentDispatcher.BeginInvoke(dispatchAction, DispatcherPriority.Send);
顺便说一句,看起来Render
优先级低于Normal
优先级:
渲染枚举值为7。 同时处理的操作 优先级为渲染。
DataBind 枚举值为8.操作是 以与数据相同的优先级处理 捆绑。
正常枚举值 是9.操作在。处理 正常优先。这是典型的 申请优先权。
发送 枚举值为10.操作 在其他之前处理 异步操作。这是 最高优先级。