-2

I've been reviewing How to call asynchronous method from synchronous method in C#? in order to get an async call to be resolved in a non-async function.

I am able to get my individual async tasks to resolve in the using Solution A of that article. But i don't see how it can be done when the single async function itself contains a call to an array of async calls. Right now it just freezes on the call

var result = task.WaitAndUnwrapException();

here is what i have

public static async Task<List<SearchModel>> GoAsync(SearchContract search, CancellationToken cancellationToken = default(CancellationToken))
        {    
            var taskList = new List<Task<List<SearchModel>>>
            {                    
                SearchRoutine1Async(search, cancellationToken),
                SearchRoutine2Async(search, cancellationToken)
            };

            Task<List<SearchModel>> completedTask = await Task.WhenAny(taskList);

            return completedTask.Result;
        }

an example of the a task is :

public static async Task<List<SearchModel>> SearchRoutine1Async(SearchContract search, CancellationToken cancellationToken = default(CancellationToken))
        {
            using (DBContext db = new DBContext)
            {
                var searchModels= await db.SearchModel
                    .Where(sm => sm.subKey1 = search.subKey1)
                    .ToListAsync(cancellationToken)
                    .ConfigureAwait(false)
                    ; 

                return searchModels;
            }
        }

The call from the synchronous routine is as follows and it FREEZES on the task.WaitAndUnwrapException...:

var task = GoAsync(search);
var result = task.WaitAndUnwrapException();

To recap... if i bypass the GoAsync routine and call the tasks individually .. it works doing this from the synchronous routine:

var task = SearchRoutine1Async(search);
var result = task.WaitAndUnwrapException();
user1161137
  • 1,067
  • 1
  • 11
  • 31

1 Answers1

1

Apparently I was missing .ConfigureAwait(false) after the

Task<List<SearchModel>> completedTask = await Task.WhenAny(taskList);

to this :

Task<List<SearchModel>> completedTask = await Task.WhenAny(taskList).ConfigureAwait(false);

@KevinGrosse thanks!

Not sure why i needed it though. Wasn't needed when running in an async pipeline.

user1161137
  • 1,067
  • 1
  • 11
  • 31
  • 1
    This is a known deadlock condition when waiting synchronously on a task. Just search "deadlock" and "ConfigureAwait", and you'll find plenty of resources explaining what happens – Kevin Gosse Nov 28 '18 at 07:30
  • If you want pipelines use the TPL Dataflow classes like TransformBlock, ActionBlock. It's not trivial to write a pipeline correctly. Or use the System.Threading.Channels classes to communicate between steps. – Panagiotis Kanavos Nov 29 '18 at 13:01