简体   繁体   中英

Asynchronous flow of C# program

To demonstrate asynchronous flow of C# I have written a simple program ( To show its difference from Python, as Python is synchronous because of GIL ).

Why is execution of func2() waiting for func1() to finish?

void main()
{
    Console.WriteLine("main");
    func1();
    func2();
}
public void func1()
{
    Console.WriteLine("func1");
    double i = 0;
    while(true)
    {
      i += 1;
      if (i > 100000000)
      {
       break;
      }
    }
    func(3);
    func(4);
}
public void func2()
{
    Console.WriteLine("func2");
    func(5);
    func(6);
}
public void func(int number)
{
    Console.WriteLine(number);
}

In func1(), I am running a loop to make program wait so that main() keep going and call func2() before func(3) and func(4). But every time, it runs in a synchronous fashion and print output in this order :

main
func1
3
4
func2
5
6

ie func2() is always called after func4() which I didn't expect in asynchronous flow.

Why is execution of func2() waiting for func1() to finish?

Thanks

C# does not make your program synchronous. All programs are synchronous (exception of multi-core). Even the OS runs synchronously and only gives the illusion of parallel processing by giving various programs time slices of execution. If you want your program to run parallel you have to explicitly tell it so. C#/.NET have many mechanisms to do this but it is not fair to say a language is asynchronous. Multi-thread code can be written in C to run on windows but if you are working on an embedded system that doesn't support parallel processing you cant.

If you want func2 not to wait for func1 to finish, you need to tell it so:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("main");
        doWork();
    }
    public async static void doWork()
    {
        Task<int> longTask = func1(); //Start func1
        func2(); //Call func2 while we wait
        int output = await longTask; //Wait for func2 to be finished
    }
    public async static Task<int> func1()
    {
        Console.WriteLine("func1");

        await Task.Delay(10000); //delay, could make func(3) and func(4) run in the meantime if we wanted....

        func(3);
        func(4);
        return 0;
    }
    public static void func2()
    {
        Console.WriteLine("func2");
        func(5);
        func(6);
    }
    public static void func(int number)
    {
         Console.WriteLine(number);
    }
}

Outputs:

main
func1
func2
5
6
3
4

This happens because every time a method is invoked, in C#, the information passed to the parameter is stored in a stack (call stack). This stack is implemented as first in last out. So in your example when the func1 is invoked it goes to stack, the main method will stop and wait for the func1 to leave the stack. https://en.wikipedia.org/wiki/Call_stack

There is no way to do what you want without asynchronous flow and I suspect it is the same for python, too.

However you can easily change your code to execute it asynchronous.

    public static void Main()
{
    Console.WriteLine("main");
    var t = func1();
    func2();
    t.Wait();
}

public static Task func1()
{
    Console.WriteLine("func1");
    return Task.Factory.StartNew(() => {
        double i = 0;
        while(true)
        {
          i += 1;
          if (i > 100000000)
          {
           break;
          }
        }
        func(3);
        func(4);
    });
}
public static void func2()
{
    Console.WriteLine("func2");
    func(5);
    func(6);
}
public static void func(int number)
{
    Console.WriteLine(number);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM