简体   繁体   English

WPF多级绑定线程问题

[英]WPF multi-level binding threading issue

just found an interesting WPF problem I could really use your help with: I've got a multi-level binding Binding="{Binding PreviewItem.Status} which produces strange behavior if and only if the properties are updated from a background thread. I used diagnostics:PresentationTraceSources.TraceLevel=High and what seems to happen is that if Status is updated, it prevents the binding from realizing the whole PreviewItem changes just a split second after it! 刚刚发现了一个有趣的WPF问题,我可以真正使用您的帮助:我有一个多级绑定Binding="{Binding PreviewItem.Status} ,当且仅当从后台线程更新属性时,它才会产生奇怪的行为。使用的diagnostics:PresentationTraceSources.TraceLevel=High ,似乎发生的是,如果Status被更新,它会阻止绑定仅在其后一秒钟内实现整个PreviewItem的更改!

I managed to reproduce the behavior in an new, empty C# test project (VS 2012, .NET 4.5). 我设法在一个新的空C#测试项目(VS 2012,.NET 4.5)中重现该行为。 This is the main code: Both channel and TimelineItem are empty classes that just have a property with all the proper notifypropertychanged event notifications, StatusType is an Enum, the control's DataContext is set to _channel : 这是主要代码:channel和TimelineItem都是空类,只是具有带有所有正确notifypropertychanged事件通知的属性,StatusType是Enum,控件的DataContext设置为_channel

Task.Run(() =>
        {
            if ( _channel.PreviewItem != null )
            {
                _channel.PreviewItem.Status = TimelineItem.StatusType.Default;
            }
            _channel.PreviewItem = new TimelineItem();
            _channel.PreviewItem.Status = TimelineItem.StatusType.Preview;
        });
}

Let's say we do this three times to create three items: 假设我们执行了三次以创建三个项目:

  1. A is created and assigned to PreviewItem, A's status goes to "Preview" (ok) A已创建并分配给PreviewItem,A的状态变为“预览”(确定)
  2. A's status goes to Default, B is created and assigned to PreviewItem (fails, binding still uses A when the status changes, updates to the new state and never re-binds to B!) A的状态变为默认,B被创建并分配给PreviewItem(失败,状态更改时绑定仍使用A,更新为新状态并且从不重新绑定到B!)
  3. B's status goes to Default, C is created and assigned to PreviewItem (ok as the status of A - where the binding is still resolved to - does not change, therefore it notices that PreviewItem has changed to C). B的状态变为“默认”,创建C并将其分配给PreviewItem(可以,因为A的状态-绑定仍解析为该状态-不会更改,因此它注意到PreviewItem已更改为C)。

If I a) move the exact same code to the main thread or b) assign the new PreviewItem BEFORE changing the old items status, the code works! 如果我a)将完全相同的代码移至主线程,或b)在更改旧项目状态之前分配新的PreviewItem,则该代码有效! Unfortunately, I cannot use either approach in my project. 不幸的是,我不能在项目中使用任何一种方法。

Anyone got an idea why this does not work? 有人知道为什么这行不通吗? As far as I understood it, WPF is supposed to take care of dispatching the change event to the proper dispatcher. 据我了解,WPF应该负责将更改事件分派给适当的分派器。 Any help is highly appreciated... 任何帮助都受到高度赞赏...

Alex 亚历克斯

UPDATE Aug 4, 2014 # 更新2014年8月4日#

For some weird reason, the bug behavior only happens on Windows 7. Whole project can be found here . 出于某些奇怪的原因,该错误行为仅发生在Windows 7上。可以在此处找到整个项目。

UPDATE Sep 2, 2014 更新2014年9月2日

The problems was resolved in a Hotfix: http://support.microsoft.com/kb/2783808/en-us 在修补程序中解决了这些问题: http : //support.microsoft.com/kb/2783808/en-us

In WPF, only the thread that created the UI (controls) may access\\modify that object. 在WPF中,只有创建UI(控件)的线程才能访问\\修改该对象。 For example, a background thread that is started from the main UI thread cannot update the contents of any control that was created on the UI thread. 例如,从主UI线程启动的后台线程无法更新在UI线程上创建的任何控件的内容。

You will need to invoke back onto the UI thread, there are multiple ways to do this, the following being one of the simplest: 您将需要重新调用UI线程,有多种方法可以执行此操作,以下是最简单的方法之一:

Application.Current.Dispatcher.Invoke(() => 
{
    // your GUI related code here
});

Can you update your .Net version to 4.5.1/4.5.2 and recheck? 您可以将.Net版本更新为4.5.1 / 4.5.2并重新检查吗? This might be a bug which might have been fixed in a recent update. 这可能是一个错误,可能已在最近的更新中修复。 I checked your code on a Windows 7 machine only and was unable to reproduce it, so it is definitively framework version related. 我仅在Windows 7机器上检查了您的代码,但无法复制它,因此它绝对与框架版本相关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM