ja. Es ist Thread-sicher. INotifyPropertyChanged
wird immer für UI-Threads von anderen Threads bereitgestellt.
Es ist nicht erforderlich, PropertyChanged
von einem anderen Thread an den Benutzeroberflächenthread zu senden, da das Ereignis PropertyChanged
automatisch an den UI-Dispatcher weitergeleitet wird.
Wie a MSDN article sagt:
Beachten Sie, dass in WPF, die Dinge anders, und der Code in Abbildung 5 funktioniert auch, wenn die Status-Eigenschaft wird auf einen Textblock dagetenbundenen. Diese ist, weil WPF das PropertyChanged-Ereignis im Gegensatz zu allen anderen XAML-Frameworks automatisch zu dem Hauptthread verschiebt. In allen anderen Frameworks wird eine Dispatcher-Lösung benötigt.
Allerdings ist es nur gilt für Änderungsbenachrichtigungen auf skalare Eigenschaften (das heißt PropertyChanged
Ereignis). Sammlungsänderungsbenachrichtigungen (INotifyCollectionChanged.CollectionChanged
Ereignis) funktionieren nicht auf diese Weise, sie müssen manuell im UI-Thread ausgelöst werden. Das heißt, wenn Sie INotifyCollectionChanged
verwenden (z. B. mit einer ObservableCollection
), werden diese Änderungen nicht zum UI-Thread gemarshallt. Dies bedeutet, dass Sie eine Ausnahme machen, wenn Sie die Sammlung aus einem nicht UI-Thread ändern. Zum Beispiel gibt es einige ViewModel
Wir sind in der Klasse ViewModel
und wir verwenden nicht den Dispatcher, um die Benutzeroberfläche zu aktualisieren. So rate ich Ihnen David Rickard Ansatz zu verwenden:
public static class DispatchService
{
public static void Invoke(Action action)
{
Dispatcher dispatchObject = Application.Current.Dispatcher;
if (dispatchObject == null || dispatchObject.CheckAccess())
{
action();
}
else
{
dispatchObject.Invoke(action);
}
}
}
und:
DispatchService.Invoke(() =>
{
this.MyCollection.Add("new value");
});
David Rickard article at msdn blog.
Update:
ja, das article verwendet MVVMLight Rahmen. Es ist jedoch nicht korrekt, dass MVVM Light verwendet, um skalare Eigenschaft zu UI-Thread zu marshalieren. Es kann aus dem Quellcode ViewModelBase
Klasse von MVVM Light
, dass there is no marshal between threads to update scalar property zu sehen. Bitte, siehe RaisePropertuChanged()
Methode.
Um auf Dispatching skalaren Eigenschaften jeden Zweifel zu zerstreuen ich einen Test gemacht haben:
XAML:
<TextBlock Text="{Binding Number}" FontSize="188" Foreground="Red" />
Ansichtsmodell:
public int Number { get; set; }
private void UpdateNumber()
{
Task.Run(() =>
{
System.Timers.Timer timer = new System.Timers.Timer(250);
timer.Elapsed += (sender, eventArgs) =>
{
Number++;
OnPropertyChanged("Number");//No exceptions, no errors
};
timer.Enabled = true;
});
}
Update 1:
Es besteht kein Zweifel, dass INotifyProperyChanged
Ereignis wird automatisch von WPF an UI-Thread gesendet. Ich glaube a MSDN article und die link hast du in deiner Frage gezeigt :).
Beachten Sie: Dies ist, weil WPF das PropertyChanged-Ereignis im Gegensatz zu allen anderen XAML-Frameworks automatisch an den Haupt-Thread sendet.
Verwenden Sie einen DispatcherTimer. Das Tick-Ereignis wird im UI-Thread ausgelöst. – Clemens