Reputation: 57
In a foreach
loop I am using Task.Run
, to call a method to do some lengthy operations for each element.
The method I'm calling is an asynch method, but for my purpose, I'm not interested in the return, and I want to return other information to the client.
The problem is that only the quickest call completes and the others are ignored. How could I make sure that each call is called separately on its own thread, without blocking the rest of the code from executing and returning?
foreach (var job in Jobs)
{
Task.Run(() => _service.DoLongAsyncCall(job)
}
Upvotes: 1
Views: 1725
Reputation: 57
Turn off the current synchronization context state to null, so each call could run independently and not have to run on the current context thus overriding each other.
the following method does exactly that. It runs operations without blocking the main thread when not awaited. And it continues to run even after returning from an API call.
Be careful to use this method only after completing all work that needs to be awaited, as this call interferes with regular async-await patterns.
public static async Task RunWithoutBlocking(IEnumerable<Func<Task>> actions)
{
var currentSyncContext = SynchronizationContext.Current;
try
{
SynchronizationContext.SetSynchronizationContext(null);
foreach (var action in actions)
{
await action();
}
}
finally
{
SynchronizationContext.SetSynchronizationContext(currentSyncContext);
}
}`
Thanks to "Dan's techie ramblings" for his helpfull article https://www.productiverage.com/i-didnt-understand-why-people-struggled-with-nets-async
Upvotes: 2
Reputation: 2764
I believe that the quickest one is completing but the others have actually not completed yet. Try something like the following:
List<Task> tasks = new List<Task>();
foreach (var printJob in PrintJobs)
{
tasks.add(Task.Run(() => _printService.Print(printJob.Label));
}
Task.WaitAll(tasks.ToArray());
This will force the main thread to block until all of the Task
s are completed.
Upvotes: 0