await 不会开启新的线程,当前线程会一直往下走直到遇到真正的Async方法(比如说HttpClient.GetStringAsync),这个方法的内部会用Task.Run或者Task.Factory.StartNew 去开启线程。也就是如果方法不是.NET为我们提供的Async方法,我们需要自己创建Task,才会真正的去创建线程。
这个这个观点应该是正确的,可后来看了很多代码后感觉还不完全是这样,毕竟一个被调用的async方法就会产生一个新的Task,而这个新的Task可能去“开启一个新线程”。改造下上面的代码测试这个问题:
public class Service { private readonly Repository _repository; public Service(Repository repository) { _repository = repository; } public async Task<string> GetUserName(int id) { Console.WriteLine(Thread.CurrentThread.ManagedThreadId); var name = await _repository.GetById(id); Console.WriteLine(Thread.CurrentThread.ManagedThreadId); return name; } } public class Repository { private DbContext _dbContext; private DbSet<User> _set; public Repository() { _dbContext = new DbContext(""); _set = _dbContext.Set<User>(); } public async Task<string> GetById(int id) { //IO... var user = await _set.FindAsync(id); return user.UserName; } }在控制台应用中执行这段代码会发现输出的两个线程Id是不相同的。
提示:控制台引用程序没有SynchronizationContext,在不恢复SynchronizationContext的情况下能更好的看出线程的变化。
到底情况是怎样的呢,这里试着分析下我的想法: