C# Event handler for WPF MVVM So I've been learning about MVVM and I had a problem. I often had to start a thread to download or do some longer task in background and when it is done change some properties so the UI updates. The problem is that the UI will update only if I changed it from the main thread. So I often had to create DispatchTimers to wait for the thread to finish and then execute some code in main. Well this is my solution to it.
With this class you can simply go to your ViewModel constructor and do something like this:
ViewModelEventHandler.RegisterEventListener(&quot;EventName&quot;, EventAction);

EventAction being an action that is executed when the event is raised.
You can simply create an async Task that does its work in the background and it raises the event &quot;EventName&quot; and then EventAction() is executed in main thread. You just have to put new ViewModelEventHandler(); inside your main function.
I also use it a lot for communication between view models. You can raise an event in view model A and a completely unrelated view model B can execute code.
Here is my code:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;

namespace MVVM {
  public class EventData &lt; T1, T2 &gt; {
    public T1 eventState {
      get;
      set;
    }
    public T2 subs {
      get;
      set;
    }
  }

  class ViewModelEventHandler {
    // holds all events and their subscribed actions, the string is the event name, bool keeps track of if the event is currently raised, and List&lt;Action&gt; holds all the functions that will be executed when the event is raised
    private static Dictionary &lt; string, EventData &lt; bool, List&lt;Action&gt; &gt;&gt; eventList = new Dictionary &lt; string, EventData &lt;bool,List&lt;Action&gt; &gt;&gt; ();


    public ViewModelEventHandler() {
      DispatcherTimer timer = new DispatcherTimer();
      timer.Interval = TimeSpan.FromMilliseconds(1);
      timer.Tick += eventListen_Tick;
      timer.Start();
    }

    public static void RaiseEvent(string eventName) {
      try {
        eventList[eventName].eventState = true;
      }
      catch {}
    }

    public static void RegisterEventListener(string eventName, Action eventMethod) {
      foreach(var regEvent in eventList) {
        if (regEvent.Key == eventName) {
          eventList[eventName].subs.Add(eventMethod);
          return;
        }
      }

      eventList[eventName] = new EventData &lt; bool, List &lt; Action &gt;&gt; ();
      eventList[eventName].eventState = false;
      eventList[eventName].subs = new List &lt; Action &gt; ();
      eventList[eventName].subs.Add(eventMethod);

    }


    public static void RemoveEventListener(string eventName, Action eventMethod) {
      try {
        eventList[eventName].subs.Remove(eventMethod);
      }
      catch {}
    }

    public static void RemoveEvent(string eventName) {
      try {
        eventList.Remove(eventName);
      }
      catch {}
    }

    private void eventListen_Tick(object sender, EventArgs e) {
      foreach(var ev in eventList) {
        if (ev.Value.eventState) {
          ev.Value.eventState = false;
          foreach(Action eventSub in ev.Value.subs) {
            eventSub();
          }
        }
      }
    }

  }
}
Your approach is wrong. It creates too complex code for a very simple and common problem. To use a sort of event aggregator to report progress is overkill.
First notice that you generally distinguish between IO bound tasks and CPU bound tasks. CPU bound tasks are executed on a background thread. The performance of CPU bound tasks can be improved by using multi threading. For example calculations are CPU bound.
CPU bound tasks should be executed in parallel using background threads.
Reading from a file or download data are IO bound tasks. The performance of IO bound tasks cannot be improved using multiple threads, but by improving the IO devices. For example a download's performance is not limited by available CPU resources, but transfer rate or other network conditions and hardware. Using a thread for IO bound tasks is a waste of resources, since IO bound operations generally require almost no CPU resources.
IO bound tasks should be executed asynchronously or event-driven.
This means you should check the library you are using to download resources for asynchronous methods and await them e.g. await DownloadAsync(). Alternatively subscribe to corresponding API events e.g. DownloadProgressChanged. Every modern UI related API exposes asynchronous methods.
Since all DispatcherObject objects are associated with a Dispatcher and each thread has its own Dispatcher, you can't use or access a DispatcherObject on a different thread then the thread the DispatcherObject was created on. Except the DispatcherObject derives from Freezable and is in a frozen state.
To access a DispatcherObject from a different thread you must use the associated Dispatcher.
The following examples show how to update e.g., a Progressbar from a background thread:
MainWindow.xaml
&lt;Window&gt;
  &lt;Progressbar x:Name=&quot;CompressionProgressbar&quot; /&gt;
&lt;/Window&gt;

MainWindow.xaml.cs
private async Task CompressData()
{
  // Start a background thread
  await Task.Run(() =&gt;
  {
    // Access the DispatcherObject from a background thread 
    // using the associated Dispatcher
    this.Dispatcher.InvokeAsync(() =&gt; this.CompressionProgressbar.Value = 33.33);
  });
}

Since .NET 4.5 the recommended approach is to use IProgress&lt;T&gt; to report progress (or delegate data back to the UI thread). The library offers a ready to use implementation, the Progress&lt;T&gt; class. The constructor captures the current SynchronizationContext to post the registered callback to it. Therefore it is important to create the instance on the UI thread and then pass it to the background thread.
private async Task CompressData()
{
  // Create an instance of Progress&lt;T&gt; using the constructor
  // to register the callback which will be executed on the current thread e.g. to report the progress
  var progressReporter = new Progress&lt;double&gt;(progressValue =&gt; this.CompressionProgressbar.Value = progressValue);

  // Start a background thread
  await Task.Run(() =&gt;
  {
    // Access the DispatcherObject from a background thread 
    // using the IProgress&lt;T&gt; instance
    progressReporter.Report(33.33);
  });
}