question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Separate synchronous and asynchronous code paths

See original GitHub issue

Most of our public API has both synchronous and asynchronous versions of service methods. Due to the big amount of logic that is identical in both synchronous and asynchronous code paths, it is acceptable to have common non-public asynchronous methods that handle both code paths.

However, synchronous execution of asynchronous method may result in any of the following issues:

  • Waiting for incomplete ValueTask. When ValueTask is created from IValueTaskSource, it is not guaranteed to return proper value (or any value at all) if GetAwaiter().GetResult() is called before task is completed. For example, implementation of InteractiveBrowserCredential has such issue: GetTokenImplAsync will return incomplete task to the GetToken while awaiting for AcquireTokenSilentAsync. See docs for details.
  • Causing a deadlock on synchronization contexts. Any single-threaded SynchronizationContext (the most common are the ones in WPF and WinForms UI threads) will hang if GetAwaiter().GetResult() is called on non-completed task in the sync context thread, and code after await operator is scheduled to be executed by the same SynchronizationContext. While ConfigureAwait(false) creates an awaitable object that forces async state machine to continue on thread pool, deadlocks are still possible.
  • Using additional thread. When GetAwaiter().GetResult() is called on non-completed task, async state machine will execute code after await on a second thread, while first thread remains blocked. This may easily lead to thread-pool starvation.
  • Causing a deadlock on callbacks. Consider the following example:
    public class Service {
        public Func<bool> Callback { get; set; }
        public void Execute() => ExecuteAsyncImpl().GetAwaiter().GetResult();
        private async Task ExecuteAsyncImpl() {
            // Do some work
            await Task.Delay(100).ConfigureAwait(false);
            if (Callback()) {
                // Do some work
                await Task.Delay(100).ConfigureAwait(false);
            }
        }
    }
    
    If user code synchronously calls ExecuteAsync from UI thread and Callback also requires UI thread, there will be a deadlock:
    private void Button_OnClick(object sender, RoutedEventArgs e) {
        var dispatcher = Dispatcher.CurrentDispatcher;
        var service = new Service { Callback = () => dispatcher.Invoke(AskUser) };
        service.Execute();
    }
    

To avoid issues described above, GetAwaiter().GetResult() must be called only on tasks that are already completed, which can be guaranteed only if asynchronous method is executed synchronously. For that, method should have a bool async parameter that is either used explicitly in conditional operators to avoid asynchronous awaiting, or passed directly into other asynchronous method with bool async parameter.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
jsquirecommented, Jun 15, 2022

@AlexanderSher: Given the age of this and the number of enhancements made to Azure.Core since, can you give a quick look as to whether there is still work to be done here or this issue is stale? If no longer needed, please close it out.

0reactions
jsquirecommented, Jun 20, 2023

@pallavit : Yes; the work for this was done quite a while back. Outside of a few special cases, all the sync calls should be using EnsureCompleted and an analyzer is in place to enforce that convention.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Synchronous vs Asynchronous | Full Guide - DataMyte
There are two ways to do things: synchronously and asynchronously. The terms explain what each programming model does and their differences.
Read more >
Asynchronous vs synchronous execution. What is the ...
Synchronous means that the caller waits for the response or completion, asynchronous that the caller continues and a response comes later (if ...
Read more >
How can async support dispatch between sync and async ...
Problem A common scenario for library authors is that they accept some callable as a callback for user-defined logic.
Read more >
Synchronous and Asynchronous Javascript
In this article, we will discuss the differences between Asynchronous and Synchronous JavaScript and detailed explanation with examples.
Read more >
Asynchronous Vs Synchronous Programming - YouTube
seems that, if you get things confused, you can replace synchronous with the word "sequential"execution ... and asynchronous with "parallel" ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found