Using synchronous methods along with asynchronous

5

For development reasons, I had to create a call to an asynchronous method in a synchronous method, but when I publish my project to the server, it is for an indefinite time running.

Asynchronous method

public static async Task<IEnumerable<T>> QueryProfileAsync<T>(this DbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
    if (HttpContext.Current.Request.IsLocal)
    {
        using (var profiled = new ProfiledDbConnection(cnn, MiniProfiler.Start()))
        {
            return await profiled.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType);
        }
    }
    else return await cnn.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType);
}

Synchronous method

public static IEnumerable<T> QueryProfile<T>(this DbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
    return QueryProfileAsync<T>(cnn, sql, param, transaction, commandTimeout, commandType).GetAwaiter().GetResult();
}

In debug mode in Visual Studio everything works perfectly. The solution was to take the call to the asynchronous method and to execute the same operations, being as follows:

public static IEnumerable<T> QueryProfile<T>(this DbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
    if (HttpContext.Current.Request.IsLocal)
    {
        using (var profiled = new ProfiledDbConnection(cnn, MiniProfiler.Start()))
        {
            return profiled.Query<T>(sql, param, transaction);
        }
    }
    else return cnn.Query<T>(sql, param, transaction);
}

The big question is: Is there a way to make a call to an asynchronous method in a synchronous method?

The need to have synchronous methods happens because it is not possible to call an asynchronous Action using Html.Action .

    
asked by anonymous 26.01.2017 / 15:07

1 answer

2

I believe a deadlock is occurring, try modifying this method QueryProfileAsync to use ConfigureAwait(false) , like this:

public static async Task<IEnumerable<T>> QueryProfileAsync<T>(this DbConnection cnn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
    if (HttpContext.Current.Request.IsLocal)
    {
        using (var profiled = new ProfiledDbConnection(cnn, MiniProfiler.Start()))
        {
            return await profiled.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType).ConfigureAwait(false);
        }
    }
    else return await cnn.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType).ConfigureAwait(false);
}

Whenever you use await to wait for an asynchronous method to run within another asynchronous method, use ConfigureAwait(false) , unless you actually need to continue running the method within the application synchronization context you are running.

Deadlock can occur for the following reason:

  • A synchronous method makes a synchronous call to an asynchronous method, thus blocking the synchronization context, while waiting for the asynchronous method to terminate
  • The asynchronous method calls another asynchronous method with await (in this case await profiled.QueryAsync<T> ) without ConfigureAwait(false)
  • When the profiled.QueryAsync<T> method ends, the QueryProfileAsync method attempts to continue its execution within the synchronization context (due to not using ConfigureAwait(false) ), but can not because the synchronous method is blocked.
  • The asynchronous method will be blocked waiting for the synchronization context to become available, but this will never occur because the synchronous method will wait indefinitely for the asynchronous method to finish.
  •   

    I recommend reading this Stephen Cleary blog post for a more detailed understanding of how it all works.

        
    02.03.2017 / 19:43