Il marshalling di database WPF cambia nel thread UI?

Ho appena notato che quando si cambiano le proprietà associate nel mio ViewModel (MVVM) da un thread di lavoro in background non ottengo eccezioni e la vista viene aggiornata correttamente. Questo significa che posso tranquillamente fare affidamento sul databinding di wpf che esegue il marshalling di tutte le modifiche nel ViewModel al thread UI? Penso di aver letto da qualche parte che si dovrebbe essere sicuri (nel ViewModel ) che INotifyPropertyChanged.PropertyChanged sia INotifyPropertyChanged.PropertyChanged sul thread dell’interfaccia utente. Questo è cambiato in 3.5 o qualcosa del genere?

Sì per gli scalari, no per le raccolte. Per le raccolte, avrai bisogno di una raccolta specializzata che effettua il marshal per te o esegui manualmente il marshalling sul thread dell’interfaccia utente tramite il Dispatcher .

Potresti aver letto che INotifyCollectionChanged.CollectionChanged deve essere INotifyCollectionChanged.CollectionChanged sul thread dell’interfaccia utente, perché semplicemente non è vero di INotifyPropertyChanged.PropertyChanged . Di seguito è riportato un esempio molto semplice che dimostra le modifiche alle proprietà dei marshall dei WPF.

Window1.xaml.cs :

 using System.ComponentModel; using System.Threading; using System.Windows; namespace WpfApplication1 { public partial class Window1 : Window { private CustomerViewModel _customerViewModel; public Window1() { InitializeComponent(); _customerViewModel = new CustomerViewModel(); DataContext = _customerViewModel; var thread = new Thread((ThreadStart)delegate { while (true) { Thread.Sleep(2000); //look ma - no marshalling! _customerViewModel.Name += "Appended"; _customerViewModel.Address.Line1 += "Appended"; } }); thread.Start(); } } public abstract class ViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } } } public class CustomerViewModel : ViewModel { private string _name; private AddressViewModel _address = new AddressViewModel(); public string Name { get { return _name; } set { if (_name != value) { _name = value; OnPropertyChanged("Name"); } } } public AddressViewModel Address { get { return _address; } } } public class AddressViewModel : ViewModel { private string _line1; public string Line1 { get { return _line1; } set { if (_line1 != value) { _line1 = value; OnPropertyChanged("Line1"); } } } } } 

Window1.xaml :

       

Credo che con 2.0 e precedenti versioni di .NET avresti ricevuto un’eccezione InvalidOperationException a causa dell’affinità del thread durante l’esecuzione dell’esempio sopra citato (il collegamento pubblicato da bitbonk è datato 2006).

Ora, con 3.5, WPF sembra effettuare il marshalling delle modifiche alle proprietà del thread in background sul dispatcher.

Quindi, in breve, dipende da quale versione di .NET stai mirando. Spero che questo chiarisca ogni confusione.

Uno dei miei colleghi Lab49’ers ne ha parlato qui nel 2007:

http://blog.lab49.com/archives/1166