2

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!

I managed to reproduce the behavior in an new, empty C# test project (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:

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)
  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!)
  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).

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! 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. Any help is highly appreciated...

Alex

UPDATE Aug 4, 2014 #

For some weird reason, the bug behavior only happens on Windows 7. Whole project can be found here.

UPDATE Sep 2, 2014

The problems was resolved in a Hotfix: http://support.microsoft.com/kb/2783808/en-us

Alex K
  • 23
  • 3
  • I can't reproduce the issue on my system. I even added a Text property to TestPreviewItem and assigned different values to every new instance. The code works as it should. Can you post your App.xaml/xaml.cs? – Yogesh Jul 30 '14 at 17:38
  • First, thanks for testing it! The App.xaml/xaml.cs is actually empty! I've [uploaded the whole test project here](http://www.filedropper.com/bindingtest). The button "task pre" shows the faulty behavior, the other two are slight modifications of the code that work. I'll also check on other machines just to make sure... – Alex K Aug 04 '14 at 08:55
  • I've checked on a couple machines with the same exe: For some weird reason, all Windows 7 machines show the WPF bug behavior, all Window 8 machines work fine?!? – Alex K Aug 04 '14 at 09:03
  • Can you update your .Net version to 4.5.1/4.5.2 and recheck? This might be a bug which might have been fixed in a recent update. I checked your code on a Windows 7 machine only, so it is definitively framework version related. – Yogesh Aug 04 '14 at 09:32
  • I already had 4.5.1 installed but after updating to 4.5.2, the problem no longer occurs! You should submit this as an answer so I can mark it as the right one. Thanks a lot! – Alex K Aug 04 '14 at 12:17
  • You are welcome. :) Posted my comment as answer. – Yogesh Aug 04 '14 at 15:09

2 Answers2

0

In WPF, only the thread that created the UI (controls) may access\modify that object. 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.

You will need to invoke back onto the UI thread, there are multiple ways to do this, the following being one of the simplest:

Application.Current.Dispatcher.Invoke(() => 
{
    // your GUI related code here
});
AwkwardCoder
  • 24,893
  • 27
  • 82
  • 152
  • Thanks for the answer, but nope. As you can see in the code samples I posted, there is nothing changing a control property (except for the data trigger), only the data object properties are set. And notifypropertychange automatically marshals the changes back to the correct thread as can be read in [this thread](http://stackoverflow.com/questions/2553333/wpf-databinding-thread-safetythis). – Alex K Jul 30 '14 at 15:27
0

Can you update your .Net version to 4.5.1/4.5.2 and recheck? 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.

Yogesh
  • 14,498
  • 6
  • 44
  • 69