Get result from UI thread to non-UI thread when using await Task.Run I have an application where I use Task to run an operation. During the operation, there can be a problem which will need some user interaction (continue or not). I need to bubble up a messagebox and get the user result back to the operation thread.

This is how I got it working:

public interface IPlugin
{
    void ConnectAndProduce(Func&lt;string, bool&gt; retryRequest);
}

public partial class MainWindow : MetroWindow
{
    [ImportMany(typeof(IPlugin))]
    private IEnumerable&lt;IPlugin&gt; Plugins;

    public MainWindow()
    {
        InitializeComponent();
    }

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        Func&lt;string, bool&gt; func = message =&gt;
        {
            var result = Application.Current.Dispatcher.Invoke(new Func&lt;Task&lt;MessageDialogResult&gt;&gt;(async () =&gt;
                {
                    var mySettings = new MetroDialogSettings()
                    {
                        AffirmativeButtonText = "YES",
                        NegativeButtonText = "NO",
                        ColorScheme = MetroDialogColorScheme.Accented
                    };

                    return await this.ShowMessageAsync("Hello!", message, MessageDialogStyle.AffirmativeAndNegative, mySettings);
                }));

            if ((result as Task&lt;MessageDialogResult&gt;).Result != MessageDialogResult.Negative)
                return true;

            return false;
        };

        ImportPlugins();
        var plugin = Plugins.FirstOrDefault();

        await Task.Run(() =&gt;
        {
            plugin.ConnectAndProduce(func);
        });
    }

    public void ImportPlugins()
    {
        var catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new DirectoryCatalog(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)));
        CompositionContainer container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }
}


And here is the Plugin what is going to do all the work:

[Export(typeof(IPlugin))]
public class Machine : IPlugin
{
    public void ConnectAndProduce(Func&lt;string, bool&gt; retryRequest)
    {
        var connection = MachineConnection();

        var retry = true;
        var retryCount = 0;
        while (retry)
        {
            if (connection != true)
                retry = retryRequest("Do you want to retry?");

            if (retryCount &lt; 3)
                retryCount++;
            else
                retry = false;
        }

        connection.Produce();
    }
}


I use MEF to load the plugin and do all the work in non-UI thread by calling the plugin method in a new Task. Once the plugin has called MachineConnect(), the connection fails and I can't just stop the plugins from working and call it again. I need to continue, and that's why the plugin has to ask if I want to retry.

Is there any better way doing the retry request from plugin to UI thread? This looks very 'hacky' to me.
You're scheduling a new non-UI operation that immediately goes back and schedules an operation to run in the UI thread, which then does some work.

Just avoid all of that, and do the work that you want to do right from the start, since you're in the UI thread:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    var mySettings = new MetroDialogSettings()
    {
        AffirmativeButtonText = "YES",
        NegativeButtonText = "NO",
        ColorScheme = MetroDialogColorScheme.Accented
    };

    var response = await this.ShowMessageAsync("Hello!", "message", MessageDialogStyle.AffirmativeAndNegative, mySettings);

    if(response == MessageDialogResult.Negative)
        return;
}