Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent async method from returning until all tasks are completed

So I'm still trying to understand the async/await pattern, but I'm also trying to achieve the following behavior:

A method A calls method B which runs a number of processes. Some of those processes can be run on separate threads while other things are being processed so that their return values will be available closer to when they are needed. Method B needs to not return control to the caller until all of these processes are completed.

Here is the test code that I am working with:

static void Main(string[] args)
{
    CallProc();
    Console.WriteLine("Program finished");
    Console.ReadKey();
}

public static async Task CallProc()
{
    var two = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(5000, "two"));
    var one = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(500, "one"));
    var three = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(1500, "three"));

    // some process happens here

    var oneMessage = await one; // waits until one finishes and then snags it's value
    Console.WriteLine("Got message {0}", oneMessage);

    // some more stuff happens here

    var twoMessage = await two; // waits until two is finished and then snags it's value
    Console.WriteLine(twoMessage);

    // TODO: need to make sure that everything is completed before returning control to caller
}

public static string SomeSynchronousProcessIDontOwn(int delayTime, string message, bool delay = true)
{
    Console.WriteLine("Starting \"{0}\"", message);
    if(delay) Thread.Sleep(delayTime);
    return string.Format("Finished \"{0}\"", message);
}

Right now, what is happening is that everything words as I expected except that the method is returning before everything is finished, so the output shows "Program finished" while "two" is still running.

How do I write this so that CallProc() can execute those tasks asynchronously but delay returning until everything has been completed. In other words, CallProc() needs to run some tasks asynchronously, but CallProc() itself needs to be called synchronously.

like image 965
Sinaesthetic Avatar asked Feb 07 '26 17:02

Sinaesthetic


1 Answers

The idea of an asynchronous method, which is what you've written is that it will return control (approximately) immediately and the task that it returns will be marked as completed when the operation that it conceptually represents finishes.

This means that your program should either be looking at the resulting task to see when it finishes, or that you don't want an asynchronous method in the first place, and you should re-write CallProc synchronously rather than asynchronously.

To make CallProc synchronous simply remove async (and adjust the return type accordingly), and wait on each task instead of using await.

If CallProc really should be asynchronous then the caller should be adding a continuation (or using await) to perform an action when the task is completed, rather than when the method returns.

like image 122
Servy Avatar answered Feb 09 '26 05:02

Servy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!