• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

C#异步

武飞扬头像
爱吃香蕉的阿豪
帮助1

异步编程是指在程序执行过程中,不需要等待某个操作完成,就可以继续执行后续的代码。比如我们开发了一个web页面中有一个上传文件功能,我们上传文件时使用异步操作,就不用等待文件的上传时间,可以先在网页上进行其他操作。但是如果我们的需求是等待上传文件完成之后才能进行下一步操作,比如我在boss上上传简历,然后根据附件简历生成在线简历,然后我在对在线简历进行优化,这时候就需要加一个await等待这个异步完成。

下面使用代码来举一个例子

创建一个 100000000个a 的超长字符串,然后把这个字符串写进d盘的文本里面

  1.  
    public static async Task Main(string[] args)
  2.  
    {
  3.  
    string str = new string('a', 100000000);
  4.  
    await File.WriteAllTextAsync("d:/1.txt", str);//加了await的异步写入
  5.  
    File.WriteAllTextAsync("d:/2.txt", str);//异步写入
  6.  
    File.WriteAllText("d:/3.txt", str);
  7.  
    }

打个断点 ,一步一步来执行

学新通

执行完第一行写入到d盘的1.txt时 ,d盘已经有了一个记事本,有很多的a,因为这句代码加了await,这里会等它执行完再到下一步。

学新通

 接着往下走,执行到最后一行代码时,虽然D盘也有2.txt了,但是由于我没有加await,此时并没有等第三句代码执行完。所以这个断点往下走时我们会发现并不会像上面一样等很久,因为异步方法会立刻返回到调用者,因此也叫(非阻塞方法)
学新通

可以看到记事本中有很多的a,但是很显然没有 100000000个,很显然是写到一半被我的断点停住了。

 学新通

 把断点继续,此时最后两句代码一起在执行,分别往2.txt和3.txt写入。

在上面的方法中加入打印线程,看一下执行过程线程的变化

  1.  
    string str = new string('a', 100000000);
  2.  
     
  3.  
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
  4.  
     
  5.  
    await File.WriteAllTextAsync("d:/1.txt", str);//加了await的异步写入
  6.  
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
  7.  
     
  8.  
    File.WriteAllTextAsync("d:/2.txt", str);//异步写入
  9.  
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
  10.  
     
  11.  
    File.WriteAllText("d:/3.txt", str);
  12.  
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);

学新通

 打印结果显示,加了await的异步方法执行完后线程发生了变化 ,因为原有线程遇见await会被解放,用于执行异步任务的线程会在任务完成后返回到await处接替原有线程继续执行任务

再举一个例子,我们自己创建一个异步方法

  1.  
    public static async Task MethodAsync()
  2.  
    {
  3.  
    await Task.Run(() =>
  4.  
    {
  5.  
    for (int i = 0; i < 1000; i )
  6.  
    {
  7.  
    Console.WriteLine(" MethodAsync " i);
  8.  
    }
  9.  
    Console.WriteLine("异步线程=====>" Thread.CurrentThread.ManagedThreadId);
  10.  
    });
  11.  
    }

再创建一个普通方法

  1.  
    public static void Method()
  2.  
    {
  3.  
    for (int i = 0; i < 1000; i )
  4.  
    {
  5.  
    Console.WriteLine(" Method " i);
  6.  
    }
  7.  
    Console.WriteLine("普通方法线程=====>" Thread.CurrentThread.ManagedThreadId);
  8.  
    }

在main方法中使用await调用异步方法

  1.  
    public static async Task Main(string[] args)
  2.  
    {
  3.  
    Console.WriteLine("线程main =====>" Thread.CurrentThread.ManagedThreadId);
  4.  
    await MethodAsync();
  5.  
    Console.WriteLine("线程main=====>" Thread.CurrentThread.ManagedThreadId);
  6.  
    Method();
  7.  
    Console.WriteLine("线程main=====>" Thread.CurrentThread.ManagedThreadId);
  8.  
    }

 把方法停在普通方法前

学新通

控制台输出👇

学新通学新通

 因为加了await,所以等待异步方法for循环完成,从控制台输出结果看出,main方法一开始的线程是1,在执行异步方法时线程是3,执行完异步方法后回到main方法,打印线程还是3,因此上面提到的

原有线程遇见await会被解放,用于执行异步任务的线程会在任务完成后返回到await处接替原有线程继续执行任务

这句话成立。

 那我们再试试不加await的

学新通

 还是一样停在刚刚的断点处,可是此时的两次主线程打印都是1,异步方法还没开始打印

学新通

 继续往下走,在控制台中发现,异步方法中新开了一个线程3,和普通方法交叉打印,最后打印主方法的线程也是原来的线程。

学新通

 学新通

学新通 

 说完await,我们再来看看async

async来修饰一个方法,表明这个方法是异步的,声明的方法的返回类型必须为:voidTaskTask<TResult>。方法内部必须含有await修饰的方法,如果方法内部没有await关键字修饰的表达式,哪怕函数被async修饰也只能算作同步方法,执行的时候也是同步执行的。

因此await和async是形影不离的,如下创建两个方法

  1.  
    Task<string> ReadAsync()
  2.  
    {
  3.  
    return File.ReadAllTextAsync(@"D:\1.txt");
  4.  
    }
  5.  
     
  6.  
    async Task<string> ReadAsync2()
  7.  
    {
  8.  
    return await File.ReadAllTextAsync(@"D:\1.txt");
  9.  
    }

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhihfbkg
系列文章
更多 icon
同类精品
更多 icon
继续加载