C# 完成的等待是否在新线程上继续其自己的异步方法?

C# 完成的等待是否在新线程上继续其自己的异步方法?,c#,async-await,C#,Async Await,我理解async/await的基本原理,但是我看到它提到了很多东西,await并没有创建新线程。我可以尊重这一点,因为await可能使用硬盘I/O或网卡或CPU以外的其他不需要新线程的地方 我想澄清的是,在等待完成后,异步函数的其余部分是否在新线程上执行?从我自己的内部测试中可以看出,它是按照以下代码执行的: public static class Program { private static void Main(string[] args)

我理解async/await的基本原理,但是我看到它提到了很多东西,await并没有创建新线程。我可以尊重这一点,因为await可能使用硬盘I/O或网卡或CPU以外的其他不需要新线程的地方

我想澄清的是,在等待完成后,异步函数的其余部分是否在新线程上执行?从我自己的内部测试中可以看出,它是按照以下代码执行的:

public static class Program
        {
            private static void Main(string[] args)
            {
                Thread.CurrentThread.Name = "ThisThread";
                AnAsyncMethod();
                while (true)
                {
                    print("External While loop. Current Thread: " + Thread.CurrentThread.Name);
                    Thread.Sleep(200);
                }
            }

            public static async void AnAsyncMethod()
            {
                for (int i = 0; i < 10; i++)
                {
                    FakeWork();
                    print("doing fake pre-await work. Current Thread: " + Thread.CurrentThread.Name);
                }
                await Task.Run(FakeWork);
                for (int i = 0; i < 10; i++)
                {
                    FakeWork();
                    print("doing fake post-await work. Current Thread: " + Thread.CurrentThread.Name);
                }
                print("hello");
            }

            public static void FakeWork()
            {
                Thread.Sleep(100);
            }

        }
公共静态类程序
{
私有静态void Main(字符串[]args)
{
Thread.CurrentThread.Name=“ThisThread”;
AnAsyncMethod();
while(true)
{
打印(“外部While循环.当前线程:“+Thread.CurrentThread.Name”);
睡眠(200);
}
}
公共静态异步void AnAsyncMethod()
{
对于(int i=0;i<10;i++)
{
伪造品();
打印(“正在进行伪等待前工作。当前线程:“+Thread.CurrentThread.Name”);
}
等待任务。运行(伪造);
对于(int i=0;i<10;i++)
{
伪造品();
打印(“正在做伪帖子等待工作。当前线程:“+Thread.CurrentThread.Name”);
}
打印(“你好”);
}
公共静态无效伪造品()
{
睡眠(100);
}
}
从这个例子来看,在异步方法中似乎使用了相同的线程,直到它遇到它的第一个等待,此时控制返回给调用方,程序继续。等待完成后,将启动一个新的独立线程在异步方法中继续,而不是封送较早的线程并强制其自身继续。这个新线程与其他地方正在使用的早期线程并发执行


这是否正确?

我已修改您的代码以显示线程id

class Program
    {
        static  void Main(string[] args)
        {
            System.Threading.Thread.CurrentThread.Name = "ThisThread";
            AnAsyncMethod();
            while (true)
            {
                Console.WriteLine("External While loop. Current Thread: " + $"{System.Threading.Thread.CurrentThread.Name}- {System.Threading.Thread.CurrentThread.ManagedThreadId}");
                System.Threading.Thread.Sleep(200);

            }
        }

        public static async void AnAsyncMethod()
        {
            for (int i = 0; i < 10; i++)
            {
                FakeWork();
                Console.WriteLine("doing fake pre-await work. Current Thread: " + $"{System.Threading.Thread.CurrentThread.Name}- {System.Threading.Thread.CurrentThread.ManagedThreadId}");
            }
            await System.Threading.Tasks.Task.Run(FakeWork);// Task.Run(FakeWork);
            for (int i = 0; i < 10; i++)
            {
                FakeWork();
                Console.WriteLine("doing fake post-await work. Current Thread: " + $"{System.Threading.Thread.CurrentThread.Name}- {System.Threading.Thread.CurrentThread.ManagedThreadId}");
            }
            Console.WriteLine("hello");
        }

        public static void FakeWork()
        {
            System.Threading.Thread.Sleep(100);
             StackTrace stackTrace = new StackTrace();

        Console.WriteLine($"Caller of Fakework method is  {stackTrace.GetFrame(1).GetMethod().Name}. Current Thread: " + $"{System.Threading.Thread.CurrentThread.Name}- {System.Threading.Thread.CurrentThread.ManagedThreadId}");

        }
    }
类程序
{
静态void Main(字符串[]参数)
{
System.Threading.Thread.CurrentThread.Name=“ThistThread”;
AnAsyncMethod();
while(true)
{
WriteLine(“外部While循环.当前线程:+$”{System.Threading.Thread.CurrentThread.Name}-{System.Threading.Thread.CurrentThread.ManagedThreadId}”);
系统线程线程睡眠(200);
}
}
公共静态异步void AnAsyncMethod()
{
对于(int i=0;i<10;i++)
{
伪造品();
WriteLine(“正在进行伪等待前工作。当前线程:+$”{System.Threading.Thread.CurrentThread.Name}-{System.Threading.Thread.CurrentThread.ManagedThreadId}”);
}
wait System.Threading.Tasks.Task.Run(FakeWork);//Task.Run(FakeWork);
对于(int i=0;i<10;i++)
{
伪造品();
WriteLine(“正在进行伪post等待工作。当前线程:+$”{System.Threading.Thread.CurrentThread.Name}-{System.Threading.Thread.CurrentThread.ManagedThreadId}”);
}
Console.WriteLine(“你好”);
}
公共静态无效伪造品()
{
系统线程线程睡眠(100);
StackTrace StackTrace=新的StackTrace();
Console.WriteLine($”Fakework方法的调用方是{stackTrace.GetFrame(1).GetMethod().Name}。当前线程:“+$”{System.Threading.Thread.CurrentThread.Name}-{System.Threading.Thread.CurrentThread.ManagedThreadId}”);
}
}
我得到这个输出

现在,您将在单独的线程中获得post WAIT。现在发生这种情况是因为

当调用Task.Run时,它将昂贵的CPU绑定操作Fakework()排入线程池队列,并接收任务句柄。Fakework()最终在下一个可用线程上并发运行

有关更多参考,请阅读cpu绑定的异步方法


所以async Wait作业是在线程池上调度任务,并基于默认的调度算法,它将使用相同的线程或派生出新线程

我修改了您的代码以显示线程id

class Program
    {
        static  void Main(string[] args)
        {
            System.Threading.Thread.CurrentThread.Name = "ThisThread";
            AnAsyncMethod();
            while (true)
            {
                Console.WriteLine("External While loop. Current Thread: " + $"{System.Threading.Thread.CurrentThread.Name}- {System.Threading.Thread.CurrentThread.ManagedThreadId}");
                System.Threading.Thread.Sleep(200);

            }
        }

        public static async void AnAsyncMethod()
        {
            for (int i = 0; i < 10; i++)
            {
                FakeWork();
                Console.WriteLine("doing fake pre-await work. Current Thread: " + $"{System.Threading.Thread.CurrentThread.Name}- {System.Threading.Thread.CurrentThread.ManagedThreadId}");
            }
            await System.Threading.Tasks.Task.Run(FakeWork);// Task.Run(FakeWork);
            for (int i = 0; i < 10; i++)
            {
                FakeWork();
                Console.WriteLine("doing fake post-await work. Current Thread: " + $"{System.Threading.Thread.CurrentThread.Name}- {System.Threading.Thread.CurrentThread.ManagedThreadId}");
            }
            Console.WriteLine("hello");
        }

        public static void FakeWork()
        {
            System.Threading.Thread.Sleep(100);
             StackTrace stackTrace = new StackTrace();

        Console.WriteLine($"Caller of Fakework method is  {stackTrace.GetFrame(1).GetMethod().Name}. Current Thread: " + $"{System.Threading.Thread.CurrentThread.Name}- {System.Threading.Thread.CurrentThread.ManagedThreadId}");

        }
    }
类程序
{
静态void Main(字符串[]参数)
{
System.Threading.Thread.CurrentThread.Name=“ThistThread”;
AnAsyncMethod();
while(true)
{
WriteLine(“外部While循环.当前线程:+$”{System.Threading.Thread.CurrentThread.Name}-{System.Threading.Thread.CurrentThread.ManagedThreadId}”);
系统线程线程睡眠(200);
}
}
公共静态异步void AnAsyncMethod()
{
对于(int i=0;i<10;i++)
{
伪造品();
WriteLine(“正在进行伪等待前工作。当前线程:+$”{System.Threading.Thread.CurrentThread.Name}-{System.Threading.Thread.CurrentThread.ManagedThreadId}”);
}
wait System.Threading.Tasks.Task.Run(FakeWork);//Task.Run(FakeWork);
对于(int i=0;i<10;i++)
{
伪造品();
WriteLine(“正在进行伪post等待工作。当前线程:+$”{System.Threading.Thread.CurrentThread.Name}-{System.Threading.Thread.CurrentThread.ManagedThreadId}”);
}
Console.WriteLine(“你好”);
}
公共静态无效伪造品()
{
系统线程线程睡眠(100);
StackTrace StackTrace=新的StackTrace();
Fakework方法的Console.WriteLine($)调用方是{stackTrace.GetFrame(1).GetMethod().Name}。当前线程:“+$”{System.Threading.Thread。
Harry is starting on thread 1
Fred is starting on thread 1
Jack is starting on thread 1
Jack is now on thread 4
Fred is now on thread 5
Harry is now on thread 6
Fred is now on thread 8
Harry is now on thread 5
Jack is now on thread 6
Fred is now on thread 7
Harry is now on thread 6
Jack is now on thread 5
Harry is now on thread 7
Fred is now on thread 5
Jack is now on thread 6
Harry is now on thread 5
Jack is now on thread 6
Fred is now on thread 9
All tasks have completed.
await Task.Yield();