You need to create an ISynchronizeInvoke for the dispatcher.
Example.
public class SynchronizeInvoke : ISynchronizeInvoke
{
private readonly System.Windows.Threading.Dispatcher dispatcher;
public SynchronizeInvoke(System.Windows.Threading.DispatcherObject dObj)
: this(dObj.Dispatcher)
{ }
public SynchronizeInvoke()
: this(Application.Current.Dispatcher)
{ }
public SynchronizeInvoke(System.Windows.Threading.Dispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
public bool InvokeRequired => !dispatcher.CheckAccess();
private class AsyncResult : IAsyncResult
{
public readonly System.Windows.Threading.DispatcherOperation operation;
public readonly IAsyncResult asyncResult;
public AsyncResult(System.Windows.Threading.DispatcherOperation operation)
{
this.operation = operation;
asyncResult = operation.Task;
}
public object? AsyncState => asyncResult.AsyncState;
public WaitHandle AsyncWaitHandle => asyncResult.AsyncWaitHandle;
public bool CompletedSynchronously => asyncResult.CompletedSynchronously;
public bool IsCompleted => asyncResult.IsCompleted;
}
public IAsyncResult BeginInvoke(Delegate method, object?[]? args) => new AsyncResult(dispatcher.BeginInvoke(method, args));
public object? EndInvoke(IAsyncResult result)
{
AsyncResult asyncResult = (AsyncResult)result;
asyncResult.operation.Task.Wait();
return asyncResult.operation.Result;
}
public object? Invoke(Delegate method, object?[]? args)
=> dispatcher.Invoke(method, args);
}
Usage:
timer.SynchronizingObject = new SynchronizeInvoke();
// or
timer.SynchronizingObject = new SynchronizeInvoke(this.Dispatcher);
// or
timer.SynchronizingObject = new SynchronizeInvoke(this);
P.S. You can simplify the implementation of SynchronizeInvoke by using undocumented behavior. In practice, this implementation works flawlessly.
public class SynchronizeInvoke : ISynchronizeInvoke
{
private readonly System.Windows.Threading.Dispatcher dispatcher;
public SynchronizeInvoke(System.Windows.Threading.DispatcherObject dObj)
: this(dObj.Dispatcher)
{ }
public SynchronizeInvoke()
: this(Application.Current.Dispatcher)
{ }
public SynchronizeInvoke(System.Windows.Threading.Dispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
public bool InvokeRequired => !dispatcher.CheckAccess();
public IAsyncResult BeginInvoke(Delegate method, object?[]? args) => dispatcher.BeginInvoke(method, args).Task;
public object? EndInvoke(IAsyncResult result)
{
Task<object> task = (Task<object>)result;
task.Wait();
return task.Result;
}
public object? Invoke(Delegate method, object?[]? args)
=> dispatcher.Invoke(method, args);
}