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.