Safe to run async delegate in synchronous method on UI?

async-await, c#

Solution

Let's look at your code:

public void MyMainMethod(){
  var getResult = Task.Run(async () => { await getResultAsync(); }).Result;
  myLabel.Text = getResult;
}

Regardless of what's taking place inside `getResultAsync`, this code is blocking the UI thread when it calls `task.Result`. In most cases, this is already wrong.

Further, the fact that your `getResultAsync` is `async` suggests there's already an async operation inside it. There is no reason to wrap it with `Task.Run`, unless you perform a mix of CPU- and IO- bound tasks inside `getResultAsync`. Even then, it may not be necessary (see this for more details).

You can control the `await` continuation context inside `getResultAsync` with `ConfiureAwait(false)`, and should do so to avoid deadlocks and redundant context switches, where possible.

So, the code can be reduced to:

public void MyMainMethod(){
  var getResult = getResultAsync().Result;
  myLabel.Text = getResult;
}

As is, it still blocks the UI. To avoid blocking, you need to make it `async`. See Async All the Way from Best Practices in Asynchronous Programming by Stephen Cleary.

If it cannot be modified to be `async` (as clarified in the update to your question), then the above is the best you can get. Indeed, it still may cause a deadlock, depending on what's going on inside `getResultAsync`, with out without `Task.Run`. To avoid deadlocks, you should not attempt to access the UI thread with a synchronous call like `control.Invoke` inside `getResultAsync`, or `await` any tasks scheduled on the UI thread with `TaskScheduler.FromCurrentSynchronizationContext`.

However, usually it is possible and desirable to re-factor the code like this into an async version:

public async Task MyMainMethod(){
  var getResult = await getResultAsync();
  myLabel.Text = getResult;
}

You would be calling it from a top-level entry point of your app, like a UI event handler:

async void Button_Click(object sender, EventArg e)
{
    try
    {
        await MyMainMethod();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Problem

If I have an application with a synchronous method, is it safe to call an async method as shown below on a UI thread or is there an issue or potential deadlock situation? I know that calling Wait will obviously cause issues, but I feel like this may work out alright. ``` public void MyMainMethod(){ var getResult = Task.Run(async () => { await getResultAsync(); }).Result; myLabel.Text = getResult; } ``` I can successfully run on a UI thread without issue, but I feel as if I may be missing something. I understand that I could use a Task and ContinueWith, but in this example, I would want to wait for the result of the async method before exiting the synchronous method. Update / Clarification In the example above, let's assume that the MyMainMethod is an overridden method or a property, etc. and cannot be modified to be async.

Original source