await和async再学习

await太不容易理解了,自己常常迷惑,不知道该怎么用。

文章:探索c#之Async、Await剖析

这篇文章,有一个很清晰的描述:

使用Async标记方法Async1为异步方法,用Await标记GetRequestStreamAsync表示方法内需要耗时的操作。主线程碰到await时会立即返回,继续以非阻塞形式执行主线程下面的逻辑。当await耗时操作完成时,继续执行Async1下面的逻辑。

static async void Async1()
    {
        HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create("http://cnblogs.com/");
        await myReq.GetRequestStreamAsync();
        //to do  当上面await耗时任务完成后,程序会回到await标记的地方继续往下执行

Console.WriteLine("请求结束了");//网络请求结束,会执行该输出
DoSomeThing();
     DoSomeThing2();
DoSomeThing3();
//方法结束 }

 以上文章可以详细阅读,在看本文。

可以反复阅读微软的介绍文章,文章标题:使用 Async 和 Await 的异步编程 (C#)

地址:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/concepts/async/index

使用async” 关键字定义的异步方法简称为“异步方法”。

下面是微软的官方示例异步方法代码:

// Three things to note in the signature:  
//  - The method has an async modifier.   
//  - The return type is Task or Task<T>. (See "Return Types" section.)  
//    Here, it is Task<int> because the return statement returns an integer.  
//  - The method name ends in "Async."  
async Task<int> AccessTheWebAsync()  
{   
    // You need to add a reference to System.Net.Http to declare client.  
    HttpClient client = new HttpClient();  

    // GetStringAsync returns a Task<string>. That means that when you await the  
    // task you'll get a string (urlContents).  
    Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");  

    // You can do work here that doesn't rely on the string from GetStringAsync.  
    DoIndependentWork();  

    // The await operator suspends AccessTheWebAsync.  
    //  - AccessTheWebAsync can't continue until getStringTask is complete.  
    //  - Meanwhile, control returns to the caller of AccessTheWebAsync.  
    //  - Control resumes here when getStringTask is complete.   
    //  - The await operator then retrieves the string result from getStringTask.  
    string urlContents = await getStringTask;  

    // The return statement specifies an integer result.  
    // Any methods that are awaiting AccessTheWebAsync retrieve the length value.  
    return urlContents.Length;  
}

这个方法需要注意四个地方:

1,方法返回类型前的关键字“async”;

2,异步方法名称以Async结尾,表示方法是异步方法(这是一种惯例,或者说约定……);

3, 方法内部有一段不好理解:

 Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");  

    // You can do work here that doesn't rely on the string from GetStringAsync.  
    DoIndependentWork();  

client的静态方法GetStringAsync也是个异步方法,当执行到方法内部的await时,会直接返回到调用方AccessTheWebAsync,也就是当前方法,所以就可以在GetStringAsync方法下调用不依赖GetStringAsync方法返回值的方法DoIndependentWork。

4,标记await的地方,是异步方法放回调用方的地方。注意这个地方!

string urlContents = await getStringTask;  

当执行到这个地方时,异步方法AccessTheWebAsync会返回调用方。这里没有写对方法AccessTheWebAsync的调用代码。

假如你在某个地方调用它的话你可以调试看一看,方法AccessTheWebAsync是不是还没执行完,就已经返回了。

以上让人主要到几点:

1,在一个方法的返回类型前加关键字async;

2,把方法名,命名为以Async结尾,方便人一眼认出这是个异步方法(因为惯例);

3,在方法内耗时调用前加上await关键字,然后执行到该处时,程序直接返回到当前方法的外部调用处,让调用处下面代码可以继续执行,当当前方法耗时任务完成时,程序再返回到await处继续向下执行,然后执行完毕该异步方法(执行完,程序会转到跳进来的地方,这个到底怎么保证,就需要额外研究了……)。

蓝色地方可能不好理解,大概意思是这么个意思:

 static void Main(string[] args)
        {
            string inputStr=Console.ReadLine();
            GetLongTimeConsumingQuery(inputStr)
            Console.WriteLine("查询中……");
            Console.ReadKey();
        }

       
        public Async void GetLongTimeConsumingQuery(string inputStr)
        {
             //在指定文件夹下,从大量txt日志文件中找到包含某个字符的错误日志

            Task<string> getStringTask=await QueryLog(inputStr)
            string logFileNames = await getStringTask;  

           Console.WriteLine("你查询的关键字在以下日志中"+logFileNames+"出现!");
           Console.WriteLine("感谢使用程序结束!");
        }

执行到方法GetLongTimeConsumingQuery内的await处,方法会返回到Main方法,调用处然后向下执行输出“查询中……”

当QueryLog方法执行完毕后,程序会跳转到await处继续向下执行。

原文地址:https://www.cnblogs.com/Tpf386/p/9702555.html