Calling an async method from a synchronous method
.net, asynchronous, c#, multithreading
Solution
`Task<TResult>.Result` (or `Task.Wait()` when there's no result) is similar to `await`, but is a synchronous operation. You should change `GetData1()` to use this. Here's the portion to change:
Task<Data> dataTask = Task.WhenAny(runningTasks).Result;
runningTasks.Remove(dataTask);
myData = gameTask.Result;
Problem
I am attempting to run async methods from a synchronous method. But I can't await the async method since I am in a synchronous method. I must not be understanding TPL as this is the fist time I'm using it. ``` private void GetAllData() { GetData1() GetData2() GetData3() } ``` Each method needs the previous method to finish as the data from the first is used for the second. However, inside each method I want to start multiple `Task` operations in order to speed up the performance. Then I want to wait for all of them to finish. GetData1 looks like this ``` internal static void GetData1 () { const int CONCURRENCY_LEVEL = 15; List<Task<Data>> dataTasks = new List<Task<Data>>(); for (int item = 0; item < TotalItems; item++) { dataTasks.Add(MyAyncMethod(State[item])); } int taskIndex = 0; //Schedule tasks to concurency level (or all) List<Task<Data>> runningTasks = new List<Task<Data>>(); while (taskIndex < CONCURRENCY_LEVEL && taskIndex < dataTasks.Count) { runningTasks.Add(dataTasks[taskIndex]); taskIndex++; } //Start tasks and wait for them to finish while (runningTasks.Count > 0) { Task<Data> dataTask = await Task.WhenAny(runningTasks); runningTasks.Remove(dataTask); myData = await dataTask; //Schedule next concurrent task if (taskIndex < dataTasks.Count) { runningTasks.Add(dataTasks[taskIndex]); taskIndex++; } } Task.WaitAll(dataTasks.ToArray()); //This probably isn't necessary } ``` I am using await here but get an Error The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task' However, if I use the async modifier this will be an asynchronous operation. Therefore, if my call to `GetData1` doesn't use the await operator won't control go to GetData2 on the first await, which is what I am trying to avoid? Is it possible to keep GetData1 as a synchronous method that calls an asynchronous method? Am I designing the Asynchronous method incorrectly? As you can see I'm quite confused. This could be a duplicate of How to call asynchronous method from synchronous method in C#? However, I'm not sure how to apply the solutions provided there as I'm starting multiple tasks, want to `WaitAny`, do a little more processing for that task, then wait for all tasks to finish before handing control back to the caller. UPDATE Here is the solution I went with based on the answers below: ``` private static List<T> RetrievePageTaskScheduler<T>( List<T> items, List<WebPageState> state, Func<WebPageState, Task<List<T>>> func) { int taskIndex = 0; // Schedule tasks to concurency level (or all) List<Task<List<T>>> runningTasks = new List<Task<List<T>>>(); while (taskIndex < CONCURRENCY_LEVEL_PER_PROCESSOR * Environment.ProcessorCount && taskIndex < state.Count) { runningTasks.Add(func(state[taskIndex])); taskIndex++; } // Start tasks and wait for them to finish while (runningTasks.Count > 0) { Task<List<T>> task = Task.WhenAny(runningTasks).Result; runningTasks.Remove(task); try { items.AddRange(task.Result); } catch (AggregateException ex) { /* Throwing this exception means that if one task fails * don't process any more of them */ // https://stackoverflow.com/questions/8853693/pattern-for-implementing-sync-methods-in-terms-of-non-parallel-task-translating System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture( ex.Flatten().InnerExceptions.First()).Throw(); } // Schedule next concurrent task if (taskIndex < state.Count) { runningTasks.Add(func(state[taskIndex])); taskIndex++; } } return items; } ```