1

I want to call step2 method after step 1 is finished. With this code below the methods step 1 and step 2 are executing in parallel. And of course I they need to be asynchronous so they won't block step 3 from executing.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace test
{
    internal class Program
    {
        static void Main(string[] args)
        {

            async void step1()
            {
                await Task.Run(() =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("step 1");
                });

            }

            async void step2()
            {
                await Task.Run(() =>
                {
                    Thread.Sleep(5000);
                    Console.WriteLine("step 2");
                });

            }

            void step3()
            {
                Console.WriteLine("step 3");
            }

            step1();
            step2();
            step3();
            
            // the code below is not working but just and idea 
            // what I want to make. If it at all posible
            // step1().step2()
            // step3() 

            Console.ReadLine();
        }
    }
}

Any help would be greatly appreciated. Keep in mind I am beginner in C#!

Edit:

  1. I know that I can get the end result even with this code.

             void step1()
             {
                 Thread.Sleep(2000);
                 Console.WriteLine("step 1");
             }
             void step2()
             {
                 Thread.Sleep(5000);
                 Console.WriteLine("step 2");
             }
             void step3()
             {
                 Console.WriteLine("step 3");
             }
             step3();
             step1();
             step2();
    

even without async/await at all.

  1. The point of this question is to make small proof of concept application where even though the code is set up like this:

             step1();
             step2();
             step3();
    

where step3() is set last will execute first because has no delay and also step2() will have to wait for step1() to finish.

Is this at all possible with async/await in C#. I think this can be done with promises in javascript.

8
  • 2
    await step1(); etc. And mark Main as async. Commented Dec 9, 2022 at 16:15
  • 1
    learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/… Commented Dec 9, 2022 at 16:16
  • 1
    Its just testcode but don't use Thread.Sleep here use Task.Delay. A Task isn't a thread. Commented Dec 9, 2022 at 16:18
  • "where step3() is set last will execute first because has no delay" - From what I understand, you're saying, "I want to call it last but run it first." I don't understand why you would want this. If you want to run it first, what is the problem with calling it first? Commented Dec 9, 2022 at 17:24
  • Like I said this is just a proof of concept app. Sometimes where step1() is some external library you don't have the luxury of calling stop3() first. Commented Dec 9, 2022 at 17:29

4 Answers 4

5

There may be a misunderstanding about how asynchronous methods work. All async methods start running synchronously, just like any other method. The magic happens when await acts on a Task that is incomplete. At that point, the method returns a new incomplete Task to the calling method (or returns nothing if it's void, which is why you should avoid async void).

So if you call step1() first, then step1() will start executing first - there is no way around that. But when step1() hits await Task.Run(...) then it returns and the Main method continues executing. At that point, you can decide what to do. Do you want to wait until step1() completes or go do something else?

Here is what the code would look like if you want:

  1. step1() to start executing first.
  2. step2() to only start after step1() completes.
  3. step3() executes as soon as possible after step1() starts, but without waiting for step1() to complete.
static async Task Main(string[] args)
{
    async Task step1()
    {
        Console.WriteLine("step 1 starting");
        await Task.Run(() =>
        {
            Thread.Sleep(2000);
            Console.WriteLine("step 1 done");
        });
    }

    async Task step2()
    {
        Console.WriteLine("step 2 starting");
        await Task.Run(() =>
        {
            Thread.Sleep(5000);
            Console.WriteLine("step 2 done");
        });
    }

    void step3()
    {
        Console.WriteLine("step 3");
    }

    var step1task = step1();
    step3();
    await step1task;
    await step2();

    Console.ReadLine();
}

The output is:

step 1 starting
step 3
step 1 done
step 2 starting
step 2 done

If you want step3() to execute before step1() even starts executing, then you need to call step3() first - no way around it.

Sign up to request clarification or add additional context in comments.

Comments

2

If you change your Main method (as well as step1 and step2) to async Task instead of void (or async void), you'll be able to await your methods.

static async Task Main(string[] args)
{
    async Task step1()
    {
        await Task.Run(() =>
        {
            Thread.Sleep(2000);
            Console.WriteLine("step 1");
        });

    }

    async Task step2()
    {
        await Task.Run(() =>
        {
            Thread.Sleep(5000);
            Console.WriteLine("step 2");
        });

    }

    void step3()
    {
        Console.WriteLine("step 3");
    }

    step3(); // You can put step3 here if you want it to run before step1 and step2.
    await step1();
    await step2();
    

    Console.ReadLine();
}

I suggest you check this Microsoft article to get a better understanding of async Task vs async void.

5 Comments

Thanks for answer! However step 3 is executed last here and not first. It should be the first method that is executed.
Sorry I didn't catch that part. I made the edit with a comment :)
Yes I can move step3 to the top and I can even not use any async/await for step1 and step2 just regular void and step 2 will be executed after step 1 for sure. But That was not the point of the question. That is why I put step3 as last.
Then you should make that clear in the question. If it comes with conditions (like can't use async there) then name them and also say why they are there.
I'm a bit confused now. Can you update the question with all the requirements?
0

If the constraints are

  1. step2 should start when step1 ends
  2. step1 and step2 should not block step3
  3. Calling code must be (e.g. no ContinueWith)

step1();
step2();
step3();

Then the answer is this is not possible.

Unless you have control of the code inside the steps, and do thread signalling to prevent step2 to start before step1 ends. Read about ManualResetEvent.

static void Main(string[] args)
{
    var mre = new ManualResetEvent(false);

    void step1()
    {
        Task.Run(() =>
        {
            Thread.Sleep(1000);
            Console.WriteLine("step 1");
            mre.Set();
        });
    }
    void step2()
    {
        Task.Run(() =>
        {
            mre.WaitOne();
            Console.WriteLine("step 2");
        });
    }
    void step3()
    {
        Console.WriteLine("step 3");
    }

    step1();
    step2();
    step3();

    Console.ReadLine();
}

Comments

-2

Drop the async, it is not meaning what you think. Use ContinueWith

    Task step1()
    {
        return Task.Run(() =>
        {
            Thread.Sleep(2000);
            Console.WriteLine("step 1");
        });
    }

    Task step2()
    {
        return Task.Run(() =>
        {
            Thread.Sleep(5000);
            Console.WriteLine("step 2");
        });
    }

    void step3()
    {
        Console.WriteLine("step 3");
    }

    var task = step1()
        .ContinueWith(x => step2());
    step3();
    task.Wait();

17 Comments

There's no reason to use .ContinueWith() over await. And while using .Wait() here doesn't really make a difference, it's a bad idea to get into the habit of using it. There's no reason to recommend it here.
Yes .Wait() here is important when I don't use await and don't have Console.ReadLine(); The Program would exist before Task is finished.
Disagree again, ContinueWith and await has two difference purposes. He want's to chain tasks, which has nothing to do with await.
But you don't need .Wait() to do that. Mark the Main() method as async and use await task;.
The OP is a self-admitted newbie. Sometimes it's better to point out the fault in the question rather than recommend something that might contribute to bad habits.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.