.NET面试准备(二)async与await

一 、执行过程
概念
  • 属于c#语言层面的语法糖,在IL层面不涉及新的指令,利用同步上下文实现并行。
  1. 执行到await操作,当前线程会被释放回到线程池,等待操作完成,线程的上下文会被保存
  2. 操作完成之后,线程池会随机取出一个线程继续执行
二、作用
  1. async 异步网络处理作用最明显:如果调用的异步方法中做了很多费时计算,那异步没有什么效果(因为await只是等待操作完成)。
  2. async 并不会开始新线程:异步与同步的执行过程是一样,执行时间也一样。异步增加请求执行数量。异步需要配合Task.Run()使用
  3. async精髓:await 时的线程回收与完成之后的线程切换
三 、死锁

原因:
指向到 jsonTask.Result.ToString(),时会出现死锁。
原因:Get方法的主线程a,在调用异步方法GetJsonAsync()时遇到await,GetStringAsync()方法开启线程b执行完毕,需要线程a执行await之后的代码,但由于线程a因为访问jsonTask.Result被阻塞,两个阻塞相互等待,形成死锁。

解决方案:
让方法一直处于异步状态中,即启用一个新的线程去await异步方法的返回结果。
在这里插入图片描述
这种方案有时还会出现错误:当调用异步方法GetJsonAsync()时,没有使用await,如下所示:

public string Get()
{
    
    
    string jsonResultString = string.Empty;

    Task.Run(async () =>
    {
    
    
        jsonResultString = GetJsonAsync(...);
     //await之后的代码
    }).Wait();//此处启动线程是为了防止Async & Await模式造成死锁
	doingSomething();
    return await jsonResultString;
}

原因:当调用异步方法后没有立刻使用await,继续向下执行,当前线程的上下文信息不会保存,当异步任务完成之后,线程池随机取出一个线程继续执行,执行时会读取当时调用它的原线程的上下文信息,因为上下文信息没有保存,会报null异常

猜你喜欢

转载自blog.csdn.net/hhhhhhenrik/article/details/91896053
今日推荐