2011-08-22 25 views
27

Son zamanlarda gerçekten kötü bir WPF hatası veriyorum. Microsoft Connect'te this bug ile aynı olduğunu düşünüyorum. Bir ViewModel bir ItemsControl içinde hareket etmek öğeleri neden olan herhangi bir mülkiyet veya koleksiyonuna bir değişiklik tetikler zaman 2010.WPF Dondurulabilir hata için geçici çözüm?

Temelde Visual Studio kullanarak

Uygulamamız hedefleri .NET 4.0 İstemci Profili, istisna bir şans var aşağıda atılacak. Her zaman olmaz ve farklı tetikleyicilere dayanarak farklı zamanlarda gerçekleşir. Uygulamayı başlattıktan kısa bir süre sonra görülüyor. İstisna isabet etmeden birkaç dakika boyunca kullanabilirsiniz, muhtemelen bu uygulama örneğinde asla vurmayacaksınız.

Connect bug raporunda olduğu gibi, ResourceDictionary'dan SolidColorBrush es'i yüklemek için {DynamicResource key} kullanıyorum. Sözlüklerin bazıları elle yüklenmiştir (destek teması için). Bu sözlüklerdeki her şeyi manuel olarak dondurmayı denedim, ancak yardımcı olmadı.

Son birkaç UserControl s, ObservableCollection s'ye bağlı ItemsControls içeren ana pencereye eklediğimde, son zamanlarda çok daha sık karşılaştık. Önceden, sadece istisna 50 kez hariç 1 kere görüyordum, ama şimdi 5 kere 5 kullanıyorum programı kullanıyorum.

Geçici çözümler için herhangi bir fikri olan var mı? Connect hatası, bunun muhtemelen bir sonraki .NET sürümünde (her ne zaman) düzeltileceğini gösterir, ancak bu hata şu anda uygulamalarımızı temelde kullanılamaz hale getirmektedir.

 
    System.InvalidOperationException: Specified value of type 'System.Windows.Media.SolidColorBrush' must have IsFrozen set to false to modify. 
     at System.Windows.Freezable.WritePreamble() 
     at System.Windows.Freezable.remove_Changed(EventHandler value) 
     at System.Windows.ResourceReferenceExpression.ResourceReferenceExpressionWeakContainer.RemoveChangedHandler() 
     at System.Windows.ResourceReferenceExpression.ResourceReferenceExpressionWeakContainer.InvalidateTargetSubProperty(Object sender, EventArgs args) 
     at System.Windows.Freezable.FireChanged() 
     at System.Windows.Freezable.Freeze(Boolean isChecking) 
     at System.Windows.Freezable.Freeze() 
     at System.Windows.Freezable.System.Windows.ISealable.Seal() 
     at System.Windows.StyleHelper.SealIfSealable(Object value) 
     at System.Windows.StyleHelper.GetChildValueHelper(UncommonField`1 dataField, ItemStructList`1& valueLookupList, DependencyProperty dp, DependencyObject container, FrameworkObject child, Int32 childIndex, Boolean styleLookup, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot) 
     at System.Windows.StyleHelper.GetChildValue(UncommonField`1 dataField, DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList`1& childRecordFromChildIndex, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot) 
     at System.Windows.StyleHelper.GetValueFromTemplatedParent(DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList`1& childRecordFromChildIndex, FrameworkElementFactory templateRoot, EffectiveValueEntry& entry) 
     at System.Windows.FrameworkElement.GetValueFromTemplatedParent(DependencyProperty dp, EffectiveValueEntry& entry) 
     at System.Windows.FrameworkElement.GetRawValue(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& entry) 
     at System.Windows.FrameworkElement.EvaluateBaseValueCore(DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry& newEntry) 
     at System.Windows.DependencyObject.EvaluateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry newEntry, OperationType operationType) 
     at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) 
     at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp) 
     at System.Windows.StyleHelper.InvalidateResourceDependentsForChild(DependencyObject container, DependencyObject child, Int32 childIndex, ResourcesChangeInfo info, FrameworkTemplate parentTemplate) 
     at System.Windows.TreeWalkHelper.InvalidateStyleAndReferences(DependencyObject d, ResourcesChangeInfo info, Boolean containsTypeOfKey) 
     at System.Windows.TreeWalkHelper.OnResourcesChanged(DependencyObject d, ResourcesChangeInfo info, Boolean raiseResourceChangedEvent) 
     at System.Windows.FrameworkElement.OnAncestorChangedInternal(TreeChangeInfo parentTreeState) 
     at System.Windows.TreeWalkHelper.OnAncestorChanged(DependencyObject d, TreeChangeInfo info) 
     at System.Windows.DescendentsWalker`1._VisitNode(DependencyObject d) 
     at MS.Internal.PrePostDescendentsWalker`1._VisitNode(DependencyObject d) 
     at System.Windows.DescendentsWalker`1.VisitNode(FrameworkElement fe) 
     at System.Windows.DescendentsWalker`1.VisitNode(DependencyObject d) 
     at System.Windows.DescendentsWalker`1.WalkFrameworkElementLogicalThenVisualChildren(FrameworkElement feParent, Boolean hasLogicalChildren) 
     at System.Windows.DescendentsWalker`1.IterateChildren(DependencyObject d) 
     at System.Windows.DescendentsWalker`1.StartWalk(DependencyObject startNode, Boolean skipStartNode) 
     at MS.Internal.PrePostDescendentsWalker`1.StartWalk(DependencyObject startNode, Boolean skipStartNode) 
     at System.Windows.TreeWalkHelper.InvalidateOnTreeChange(FrameworkElement fe, FrameworkContentElement fce, DependencyObject parent, Boolean isAddOperation) 
     at System.Windows.FrameworkElement.OnVisualParentChanged(DependencyObject oldParent) 
     at System.Windows.Media.Visual.FireOnVisualParentChanged(DependencyObject oldParent) 
     at System.Windows.Media.Visual.RemoveVisualChild(Visual child) 
     at System.Windows.Media.VisualCollection.DisconnectChild(Int32 index) 
     at System.Windows.Media.VisualCollection.Clear() 
     at System.Windows.Controls.UIElementCollection.ClearInternal() 
     at System.Windows.Controls.Panel.ClearChildren() 
     at System.Windows.Controls.Panel.OnItemsChangedInternal(Object sender, ItemsChangedEventArgs args) 
     at System.Windows.Controls.Panel.OnItemsChanged(Object sender, ItemsChangedEventArgs args) 
     at System.Windows.Controls.ItemContainerGenerator.OnRefresh() 
     at System.Windows.Controls.ItemContainerGenerator.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) 
     at System.Windows.Controls.ItemContainerGenerator.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) 
     at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) 
     at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) 
     at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) 
     at System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e) 
     at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) 
     at System.Windows.Controls.ItemCollection.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) 
     at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) 
     at System.Windows.WeakEventManager.DeliverEvent(Object sender, EventArgs args) 
     at System.Collections.Specialized.CollectionChangedEventManager.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args) 
     at System.Windows.Data.CollectionView.OnCollectionChanged(NotifyCollectionChangedEventArgs args) 
     at System.Windows.Data.ListCollectionView.RefreshOverride() 
     at System.Windows.Data.CollectionView.Refresh() 
     at System.Windows.Data.CollectionView.EndDefer() 
     at System.Windows.Data.CollectionView.DeferHelper.Dispose() 
     at System.Windows.Controls.ItemCollection.SetCollectionView(CollectionView view) 
     at System.Windows.Controls.ItemCollection.SetItemsSource(IEnumerable value) 
     at System.Windows.Controls.ItemsControl.OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
     at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
     at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args) 
     at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType) 
     at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp) 
     at System.Windows.Data.BindingExpressionBase.Invalidate(Boolean isASubPropertyChange) 
     at System.Windows.Data.BindingExpression.TransferValue(Object newValue, Boolean isASubPropertyChange) 
     at System.Windows.Data.BindingExpression.ScheduleTransfer(Boolean isASubPropertyChange) 
     at MS.Internal.Data.ClrBindingWorker.NewValueAvailable(Boolean dependencySourcesChanged, Boolean initialValue, Boolean isASubPropertyChange) 
     at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange) 
     at MS.Internal.Data.ClrBindingWorker.OnSourcePropertyChanged(Object o, String propName) 
     at MS.Internal.Data.PropertyPathWorker.System.Windows.IWeakEventListener.ReceiveWeakEvent(Type managerType, Object sender, EventArgs e) 
     at System.Windows.WeakEventManager.DeliverEventToList(Object sender, EventArgs args, ListenerList list) 
     at System.ComponentModel.PropertyChangedEventManager.OnPropertyChanged(Object sender, PropertyChangedEventArgs args) 
     at ***.ViewModelBase.OnPropertyChanged(String name) in c:\***\ViewModelBase.cs:line 17 
    ..... 

DÜZENLEME: Ayrıca sadece bizim ViewModel temel sınıfın PropertyChanged olay içine atılan herhangi InvalidOperationException s bastırmak denedim. Bu durum istisnaların sayısını biraz azaltmış görünüyordu, ama şimdi sadece ObservableCollection'un CollectionChanged etkinliğinde vurduk.

+0

Kodunuzda OnPropertyChanged'i farklı bir öncelikle Dispatcher.Invoke kullanarak yükseltmeyi denediniz mi - eğer mümkünse? Bazen etkilemek için kullandığım bir şey - biraz rastgele Katılıyorum :-) Yarış koşullarında WPF ... –

+2

Vahşi bir tahmin, ama belki de referansta kullanılan tüm fırça kaynaklarını, bunların örneklenmesinde dondurabilir misiniz? Burada nasıl yapılacağını buradan okuyabilirsiniz: http://stackoverflow.com/questions/799890/how-can-wpf-objects-deriving-from-freezable-be-frozen-in-xaml –

+0

Ayrıca, Sadece UI iş parçacığındaki ObservableCollection'ı değiştiriyor musunuz? –

cevap

20

Bu .net hatasına geçici çözüm bulmak için, kodunuzdaki tüm Katı Renk Fırçalarını dondurulabilir olarak değiştirin.ayrıntılı talimatlar burada göremiyor fazlası için

<SolidColorBrush po:Freeze="True" x:Key="WindowBackground" Color="Black" />. 

: Örneğin:

<SolidColorBrush x:Key="WindowBackground" Color="Black" /> 

şekilde değiştirilmelidir How can WPF objects deriving from Freezable be frozen in XAML?.

+0

Bu, bunu düzeltmiş gibi görünüyor! Ben sözlükleri yüklerken manuel dondurma tamamen çalışma değildi sanırım. –

+0

harika! ne kadar basit, tamamen bana yardımcı oldu. –

+2

"po:" nedir merak ediyorum? – tofutim

0

ItemsControl ve türetilmiş kontroller ile MVVM hakkında buggy davranış turu her geldiğinde ilk denemem VirtualizingStackPanel'i devre dışı bırakmaktır.

<ItemsControl VirtualizingStackPanel.IsVirtualizing="False" /> 

Sadece bir deneyin

...

+1

Bunu denedim ve uygulamayı her ComboBox/ItemsControl/ListBox'ta ayarladım. Bir fark yaratmıyor gibi görünüyor. –

3

inanmıyorum bunun için bir iş çevresinde bulunmaktadır. Bu kendimle başa çıkmak zorunda kaldığımda, WPF okuduklarımdan kaynak yaratıyor. Yani, bu kaynak üzerinde bir DynamicResource kullanmaya çalıştığınızda, dondurulabilir istisna elde edersiniz. 'Stiller ve şablonları çoklu iş parçacığı üzerinde kullanılabilir

"WPF bir stil veya şablon içindeki herhangi freezables donacak ve freezables yapabilirsiniz. Burada

neyi oluyor Microsoft Foundation Ekibi bir alıntı t donmadıklarsa, şu anda Application.Resources içinde bulunan herhangi bir probleme 'u genişletmeyi düşünüyoruz, çünkü aynı iş parçacığı problemi var ... Dondurulmuş bir dondurucuda DynamicResource çalışmıyor, çünkü bir dondurulmuş dondurulabilir potansiyel olarak birden fazla veli var - bu yüzden ebeveyni r esource."

+0

'DynamicResource' donmuş 'Freezable' işe yarar - bu uygulama işe başlar ve zamanın çok iyi çalışır. Referans verdiğim kaynaklar, sadece içinde dinamik veya statik kaynak aramaları olmayan fırçalar gibi şeylerdir. Hepsi şöyle görünüyor: '' Ayrıca, söyleyebildiğim kadarıyla, WPF, sözlük yüklendiğinde işleri otomatik olarak dondurmuyor gibi görünüyor. Bu yüzden onları elle donduruyorum. –

İlgili konular