Sto sbattendo la testa contro il muro virtuale da giorni ormai. Il metodo BindingOperations.EnableSynchronization sembra funzionare solo in .NET 4.5.ObservableCollection non thread-safe anche in .NET 4.5?
ho scritto un test che non riesce a volte:
object blah = new object();
Application app = Application.Current == null ? new Application() : Application.Current;
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
ObservableCollection<ThreadSafeObservableTestObject> collection = null;
collection = new ObservableCollection<ThreadSafeObservableTestObject>();
BindingOperations.EnableCollectionSynchronization(collection, blah);
CollectionTestWindow w = new CollectionTestWindow();
Task.Factory.StartNew(() =>
{
Thread.Sleep(2000);
w.TestCollection = collection;
collection.CollectionChanged += collection_CollectionChanged;
collection.Add(new ThreadSafeObservableTestObject() { ID = 1, Name = "Sandra Bullock" });
collection.Add(new ThreadSafeObservableTestObject() { ID = 2, Name = "Jennifer Aniston" });
collection.Add(new ThreadSafeObservableTestObject() { ID = 3, Name = "Jennifer Lopez" });
collection.Add(new ThreadSafeObservableTestObject() { ID = 4, Name = "Angelina Jolie" });
collection.Add(new ThreadSafeObservableTestObject() { ID = 5, Name = "Mary Elizabeth Mastrantonio" });
Thread.Sleep(5000);
System.Windows.Application.Current.Dispatcher.Invoke(() => w.Close());
System.Windows.Application.Current.Dispatcher.Invoke(() => Application.Current.Shutdown());
});
app.Run(w);
Il TestCollectionWindow assomiglia a questo:
<ItemsControl ItemsSource="{Binding TestCollection}" Name="list">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding ID}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Quindi nulla di magico qui. Ma il risultato è quasi ogni volta che alcune voci sono due volte nell'interfaccia utente - gli stessi oggetti! La finestra risultato appare come questo allora:
Sandra Bullock 1
Jennifer Aniston 2
Jennifer Lopez 3
Angelina Jolie 4
Mary Elizabeth Mastrantonio 5
Jennifer Aniston 2
Come puoi vedere chiaramente, Jennifer Aniston è elencata due volte. Questo può essere riprodotto facilmente. Si tratta di un problema generale o c'è qualcosa di sbagliato in questo test, ad esempio una istanza di applicazione imperfetta?
Grazie in anticipo!
maggior parte delle classi di raccolta non sono thread-safe e non lo saranno mai. La sicurezza del thread è ** difficile ** e richiede API diverse. Guarda le collezioni concorrenti. – SLaks
Forse dovresti controllare lo spazio dei nomi ['System.Collections.Concurrent'] (http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx). –
Provate questa raccolta che si prende cura di questo problema e di altri problemi multi-thread che inevitabilmente emergeranno con altri approcci: http://www.codeproject.com/Articles/64936/Multithreaded-ObservableImmutableCollection – Anthony