一文看懂系列--Async await和同步方法区别

1. async/await 与同步方法的执行顺序

无论是使用 async/await 还是同步方法,它们的执行顺序是相同的,都是按照代码书写的顺序执行的。关键的区别在于 异步方法执行时不会阻塞线程,而同步方法会阻塞线程

代码执行顺序:
  • 同步方法:代码按照顺序执行,遇到耗时操作时(如 I/O 操作、网络请求等),整个线程会被阻塞,直到操作完成后,继续执行后续代码。
  • 异步方法 (async/await):代码同样是按顺序执行的,但在遇到 await 时,异步方法会挂起并将控制权交还给调用线程,等待异步操作完成,不会阻塞线程。一旦异步操作完成,方法会恢复执行后续代码。

2. 同步方法(会阻塞线程)

同步方法会直接阻塞当前线程,直到执行完当前操作。比如,如果你调用了一个网络请求的同步方法,线程会一直等待,直到请求完成,才继续执行后续代码。

示例:
public OperateResult CommandEx(EnumCommand command, bool someFlag)
{
    // 假设这是一个同步的长时间操作(比如网络请求、文件读取等)
    SomeLongOperation();  // 这会阻塞当前线程
    return new OperateResult { IsSuccess = true };  // 返回结果
}
  • 在这种情况下,SomeLongOperation() 执行时,当前线程(通常是主线程)会被阻塞,不能执行其他操作。
  • 直到 SomeLongOperation() 执行完成,才会继续执行 return new OperateResult { IsSuccess = true };

3. 异步方法(不会阻塞线程)

异步方法使用 async/await 后,执行时会让出控制权给调用线程,异步操作(如 SomeAsyncOperation())执行时不会阻塞当前线程。

示例:
public async Task<OperateResult> CommandEx(EnumCommand command, bool someFlag)
{
    // 假设这是一个异步的长时间操作(比如网络请求、文件读取等)
    await SomeAsyncOperation();  // 这里不会阻塞线程
    return new OperateResult { IsSuccess = true };  // 返回结果
}
  • 在这种情况下,SomeAsyncOperation() 被 await 后,异步操作开始执行,但 不会阻塞当前线程
  • 当 SomeAsyncOperation() 执行时,主线程可以继续做其他事情(比如响应用户界面事件或处理其他请求)。
  • 等到 SomeAsyncOperation() 完成后,await 语句会恢复方法的执行,继续执行后面的代码 return new OperateResult { IsSuccess = true };

总结:

  • 同步方法:会阻塞当前线程,直到操作完成。例如,执行一个耗时的网络请求时,线程会一直等待,不能处理其他操作。
  • 异步方法:使用 async/await 后,异步操作不会阻塞线程。线程可以继续执行其他任务,直到异步操作完成后,才会恢复执行后续代码。

关键区别

  • 阻塞:同步方法会阻塞线程,异步方法不会阻塞线程。
  • 线程利用:异步方法利用线程空闲时间来执行其他任务,而同步方法需要等待任务完成才能继续。

这就是 async/await 和同步方法的主要差异。async/await 使得应用程序更加高效,特别是在处理 I/O 密集型操作时,可以避免主线程被阻塞,提高应用的响应能力。

代码补充:

4.1同步方法代码:
public class DataFetcher
{
    // 模拟同步操作,发起一个网络请求并等待结果
    public string FetchDataSync(string url)
    {
        // 模拟长时间的网络请求(例如,HTTP 请求)
        var result = SomeLongNetworkRequest(url);  // 同步操作,阻塞线程
        return result;
    }

    // 模拟一个同步的网络请求操作(实际上是阻塞的)
    private string SomeLongNetworkRequest(string url)
    {
        // 这里模拟的网络请求实际上是阻塞的
        System.Threading.Thread.Sleep(5000);  // 假装等待了 5 秒钟
        return "Server Response";
    }
}

​

在上面的同步方法中,SomeLongNetworkRequest()阻塞当前线程,直到网络请求完成。整个过程需要 5 秒钟,期间主线程不能做其他事情。 

4.2异步方法代码:
public class DataFetcher
{
    // 模拟异步操作,发起一个网络请求并等待结果
    public async Task<string> FetchDataAsync(string url)
    {
        // 使用异步方法来发起网络请求
        var result = await SomeLongNetworkRequestAsync(url);  // 异步操作,不阻塞线程
        return result;
    }

    // 模拟一个异步的网络请求操作(实际上是非阻塞的)
    private async Task<string> SomeLongNetworkRequestAsync(string url)
    {
        // 异步操作,不会阻塞线程
        await Task.Delay(5000);  // 模拟等待 5 秒钟(例如网络延迟)
        return "Server Response";
    }
}

//2.异步方法调用
public class Program
{
    public static async Task Main()
    {
        var fetcher = new DataFetcher();
        Console.WriteLine("Fetching data asynchronously...");
        
        // 调用异步方法
        string data = await fetcher.FetchDataAsync("https://example.com");

        // 数据获取完成后
        Console.WriteLine("Data fetched: " + data);
    }
}

在异步方法中,SomeLongNetworkRequestAsync() 使用 await 关键字,这意味着 异步操作 会释放当前线程,并且不阻塞主线程。即使网络请求还没有完成,主线程也可以继续执行其他任务,而一旦网络请求完成,await 会继续执行并返回结果。

4.3. 对比分析
  • 同步方法

    • 主线程在执行 SomeLongNetworkRequest() 时会被 阻塞,无法继续执行其他任务,直到请求完成。
    • 如果网络请求时间长,主线程可能需要等待较长时间(例如 5 秒钟)。
  • 异步方法

  • 当你调用 FetchDataAsync 时:

    • 主线程开始执行 FetchDataAsync,并遇到 await SomeLongNetworkRequestAsync(url),此时 主线程解放,去执行其他不同方法体内的方法的操作(比如 UI 更新方法)。
    • 当第一个请求完成后,控制权返回到 await 后面的位置,执行后续代码,即打印“First request completed”,然后继续执行第二个异步请求。

    • 异步操作是 顺序执行的,第二个请求在第一个请求完成后才会开始。

    • 当请求完成时,await 会恢复并继续执行后面的代码,整个过程不会影响主线程的其他任务。
4.4. 总结
  • 同步方法适用于不涉及 I/O 操作或耗时任务较短的场景。它简单,但会 阻塞线程,导致性能瓶颈。
  • 异步方法则适用于 I/O 密集型任务,能够提高程序的 响应性,特别是在需要等待外部资源(如网络、数据库等)的情况下,不会造成主线程阻塞。

async await-- 异步调用,顺序执行,解放主线程,await之后的方法是一个Task类型的异步方法(I/O操作密集型耗时方法)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值