You can use the following code to run actions on the UI thread - it is optimized as it first determines the 'thread context' the caller is running on:
/// <summary>
/// utility function to enable an action to run on the UI thread (if not already)
/// </summary>
/// <param name="action">the action to execute</param>
/// <returns></returns>
internal static void RunOnUiThread(Action action)
{
try
{
if (IsOnUiThread)
action();
else
Application.Current.Dispatcher.BeginInvoke(action);
}
catch (Exception ex)
{
MessageBox.Show($@"Error in OpenAndActivateMap: {ex.Message}");
}
}
/// <summary>
/// Determines whether the calling thread is the thread associated with this
/// System.Windows.Threading.Dispatcher, the UI thread.
///
/// If called from a View model test it always returns true.
/// </summary>
public static bool IsOnUiThread => ArcGIS.Desktop.Framework.FrameworkApplication.TestMode || System.Windows.Application.Current.Dispatcher.CheckAccess();
You can then 'invoke' your UI actions like this:
// simple action
RunOnUiThread(() => { /* UI action functionality */ });
// action with await
RunOnUiThread(async () => { /* UI action functionality with await */ });
I think in most cases you should refrain from using Dispatcher.Invoke because it's a blocking call (meaning it doesn't return to you until it has been executed), instead you should use Dispatcher.BeginInvoke which is non blocking.
Also there's another issue I noticed as the following code snippet with block the 'main CIM thread' for 4 seconds:
await QueuedTask.Run(() => {
Task.Delay(4000).Wait();
// delayed action
});
So I would recommend to run a 'delay' from an asynchronous task using something like this (this is a Pro button's OnClick method):
internal class TestDelay : Button
{
protected override void OnClick()
{
_ = DelayTaskAsync();
System.Diagnostics.Debug.WriteLine("OnClick done");
}
static async Task DelayTaskAsync()
{
Task delay = Task.Delay(5000);
await delay;
// do your delayed action here
System.Diagnostics.Debug.WriteLine("Delayed action");
}
}
This will not block the UI nor the CIM thread.