async/await未用await结合Task是否创建新线程?及相关疑问求助
关于async/await线程与Task的疑问解答
问题1:调用不带await的async函数getData()时,是否会创建新线程处理该函数,主线程不会被阻塞?
不会创建新线程,主线程反而会被阻塞。
async方法的执行逻辑是:调用后会同步执行到第一个await语句,如果方法里没有任何await(比如你的getData),那整个方法会在调用它的线程(也就是getValue所在的主线程)上从头到尾同步跑完。这意味着主线程会卡在getData的大循环里,直到循环结束才会回到getValue继续执行。
如果你的实际运行结果是主线程没被阻塞,那大概率是代码里有遗漏(比如循环被包装进了Task.Run,或者加了await),否则按你贴的代码,主线程一定会被循环阻塞。
问题2:返回类型Task的作用是什么?它是否会参与线程创建?
Task就是个异步操作的状态管理器,它本身不负责创建线程。
它的核心作用包括:
- 标记方法是异步的,让调用方可以通过
await等待操作完成,或者绑定后续执行逻辑; - 存储异步操作的结果(
Task<TResult>)、异常状态,方便调用方获取执行信息; - 线程的创建完全取决于异步操作的具体实现:比如用
Task.Run会把代码丢到线程池线程执行,而像HttpClient.GetAsync这类IO异步操作,根本不需要额外线程,靠操作系统的IO完成端口就能实现异步。
问题3:代码运行输出为1,2,ended,3,为何2会在ended之前打印?
按你贴的代码,这个输出是不符合逻辑的,正常运行应该是1,2,3,ended。
因为你的getData没有await,调用时会同步执行:
getValue打印1;- 进入
getData,打印2,然后执行大循环(主线程被阻塞); - 循环结束后打印
3,getData返回Task; - 回到
getValue打印ended。
如果实际输出是1,2,ended,3,那说明getData里的循环是异步执行的——比如你代码里的getData实际加了await(比如把循环放到await Task.Run(() => { ... })里)。这时候:
getValue打印1;- 进入
getData,打印2后遇到await,此时getData会返回一个未完成的Task,主线程立刻回到getValue打印ended; - 当
await的异步操作完成后,getData的剩余代码继续执行,打印3。
这样就会出现你说的输出顺序。
内容的提问来源于stack exchange,提问作者Parth
相关产品推荐
相关产品推荐

