-2

For the last 10 years, I was using WPF with the "Dispatcher" in order to ensure UI thread will receive notifications. I was using code like this in a base "Model" class:

[NotifyPropertyChangedInvocator]
public void RaisePropertyChanged([CallerMemberName] String propertyName = "")
{
    var propertyChanged = PropertyChanged;

    if (propertyChanged != null)
    {

        if (Dispatcher == null) // For console App
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
        else
        {
            if (Dispatcher.CheckAccess())
            {
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            else
            {
                Dispatcher.Invoke(new Action(() => propertyChanged(this, new PropertyChangedEventArgs(propertyName))));
            }
        }
    }
}

In this SO Question, some talk about AsynContext, another seems to add nuget package "Microsoft.NET.Sdk.WindowsDesktop" which seems to be Windows OS dependant.

What is the recommended way to do the equivalent in new Desktop application? Where is the Dispatcher? Is there any equivalent? Can we keep our code OS independant? Should we wait few months more until Microsoft will come with an OS independant solution?

Eric Ouellet
  • 10,996
  • 11
  • 84
  • 119
  • `Microsoft.NET.Sdk.WindowsDesktop` is for .NET Core 3 – Pavel Anikhouski Jan 27 '20 at 15:48
  • WPF runs on Windows only so what do you mean by an "OS independant" solution? The `Dispatcher` is still there. – mm8 Jan 27 '20 at 15:48
  • I thought that Core was mainly there as a common base for the 3 OS (Windows, IOS and Unix) in order to create WPF alike application (without being exactly and solely for Windows). I feel that Microsoft.NET.Sdk.WindowsDesktop is a temporary patch and I was asking myself if there is not a better way to do WPF alike app that would stay OS Independant? – Eric Ouellet Jan 27 '20 at 16:09
  • Also, I was wondering if I would be better using AsyncContext (Seems OS-Independant) instead of a Dispatcher (Windows Specific) and if AsyncContext is enough to manage something like INotifyPropertyChanged – Eric Ouellet Jan 27 '20 at 16:12
  • 1
    Maybe you should consider Avalonia. You might also consider searching on "wpf notifypropertychanged marshalled". Eg https://stackoverflow.com/questions/6773908/wpf-are-notifypropertychangeds-marshalled-to-the-dispatcher – Andy Jan 27 '20 at 20:01
  • @Andy, Thanks. About Avalonia, although it seems to have lots of contributors, I prefer to stay with Microsoft framework. About marshalling NotifyPropertyChanged event object, I'm actually wondering what is the right way to do it in 2020?... Should I use a Dispatcher (which sems to be tied to Windows only), a SyncronisationContext (and then how to make sure that is the UI thread) and why the proposed choice? – Eric Ouellet Jan 27 '20 at 20:26
  • Wpf = windows. Only. In 2020 and beyond. Net old and net core. Windows only. No need for dispatcher or anything. It's marshalled already. – Andy Jan 27 '20 at 20:41
  • Why do you say it is marshalled? Are you saying that a change that happen on a worker thread will be notified on UI thread by magic? All WPF is made with Dispatcher.CheckAccess everywhere to ensure nobody try to update UI from worker thread. If it is not that, then what do you mean by marshalling and how does that applied? – Eric Ouellet Jan 27 '20 at 20:54

1 Answers1

0

WPF still runs on Windows only and the Dispatcher is still there so your issue is a bit unclear.

If you are developing a class library to be consumed by different client applications running on different platforms, you could hide the Dispatcher behind an interface that you then implement in each supported client platform.

Interface:

public interface IDispatcher
{
    bool CheckAccess();
    void Invoke(Action action);
}

View Model:

public ViewModel(IDispatch dispatcher) { ... }

WPF implementation:

public class WpfDispatcher : IDispatcher
{
    private readonly Dispatcher _dispatcher;

    public WpfDispatcher(Dispatcher dispatcher) =>
        _dispatcher = dispatcher;

    public bool CheckAccess() => _dispatcher.CheckAccess();

    public void Invoke(Action action) => _dispatcher.Invoke(action);
}
mm8
  • 163,881
  • 10
  • 57
  • 88