C#异步方法测试

异步方法是否意味着多线程

答案是否定的,请看如下源码

class Program
    {
        static async Task Main(string[] args)
        {
            decimal maxDec = decimal.MaxValue;
            Console.WriteLine($"main thread id:{Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine();
            decimal sum1 = await GetSumAsync(1000000000L);
            
            Console.WriteLine($"main thread id after async1:{Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine();

            decimal sum2 = await GetSumAsync(100000000);            
            Console.WriteLine($"main thread id after async2:{Thread.CurrentThread.ManagedThreadId}");
            Console.ReadKey();
        }


        static async Task<decimal> GetSumAsync(long n)
        {
            Console.WriteLine($"async method thread id1:{Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine();
            decimal sum = 0;
            Random rand = new Random();
            for (int i = 0; i < n; i++)
            {
                sum += rand.Next(10000);
            }

            Console.WriteLine($"async method thread id2:{Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine();
            return sum;
        }

执行结果如下图,可以看到线程ID没有发生变化。

 为什么.net提供的有些API在调用异步方法之后线程ID变了呢

请看如下代码

static async Task Main(string[] args)
        {
            decimal maxDec = decimal.MaxValue;
            Console.WriteLine($"main thread id:{Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine();
            
            string str = new string('a', 10000000);
            await File.WriteAllTextAsync(@"C:\test\1.txt", str);
            Console.WriteLine($"main thread id after async1:{Thread.CurrentThread.ManagedThreadId}");
            Console.WriteLine();

            
            await File.WriteAllTextAsync(@"C:\test\1.txt", str);
            Console.WriteLine($"main thread id after async2:{Thread.CurrentThread.ManagedThreadId}");
            Console.ReadKey();
        }

执行完成之后结果如下:

可以看到执行完第一次的 WriteAllTextAsync方法之后线程ID变了,执行完第二次的WriteAllTextAsync之后线程ID没变,这是为什么呢?

通过查看net的runtime相关代码,可以看到有如下一段:

// Rent the reusable ThreadPoolValueTaskSource, or create a new one to use if we couldn't get one (which
        // should only happen on first use or if the SafeFileHandle is being used concurrently).
        internal ThreadPoolValueTaskSource GetThreadPoolValueTaskSource() =>
            Interlocked.Exchange(ref _reusableThreadPoolValueTaskSource, null) ?? new ThreadPoolValueTaskSource(this);

原来是在异步方法里面首先尝试使用原来的线程,没拿到的话会开启一个新的线程。

综上,异步方法本身不会开启新的线程,除非方法内部编写代码开启。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值