zoukankan      html  css  js  c++  java
  • C#异步编程二

    上一异步编程的博客还是在9月份的,最近事情也比较多,烦恼事情一个接着一个,一个人的周末除了无聊就剩无聊了,也只有写写博客来打发下这无聊的时光。原本想着尽快把异步编程这块总结一下,之前把委托异步算是总结了下,这次主要是想着把async await总结一下。在学习async await的同时顺便也得把task了解一下,这里只是大概的了解。因为想着在以后的多线程中在细细总结。

    在总结之前,需要了解task下,Task启动的线程是后台线程,不过可以通过在Main方法中调用task.Wait()方法,使应用程序等待task执行完毕。Task与Thread的一个重要区分点是:Task底层是使用线程池的,而Thread每次实例化都会创建一个新的线程。

        class Program
        {
            static void DoRun1()
            {
                Console.WriteLine("Thread Id =" + Thread.CurrentThread.ManagedThreadId);
            }
    
            static void DoRun2()
            {
                Thread.Sleep(50);
                Console.WriteLine("Task调用Thread Id =" + Thread.CurrentThread.ManagedThreadId);
            }
    
            static void Main(string[] args)
            {
                for (int i = 0; i < 50; i++)
                {
                    new Thread(DoRun1).Start();
                }
    
                for (int i = 0; i < 50; i++)
                {
                    Task.Run(() => { DoRun2(); });
                }
    
                //让应用程序不立即退出
                Console.Read();
            }
        }

    可以看到DoRun1()方法每次的Thread Id都是不同的,而DoRun2()方法的Thread Id是重复出现的。我们知道线程的创建和销毁是一个开销比较大的操作,Task.Run()每次执行将不会立即创建一个新线程,而是到CLR线程池查看是否有空闲的线程,有的话就取一个线程处理这个请求,处理完请求后再把线程放回线程池,这个线程也不会立即撤销,而是设置为空闲状态,可供线程池再次调度,从而减少开销。

    Task<TResult>是Task的泛型版本,这两个之间的最大不同是Task<TResult>可以有一个返回值。

            static void Main(string[] args)
            {
                Console.WriteLine("主线程开始");
    
                Task<string> task = Task<string>.Run(() => { Thread.Sleep(1000); return Thread.CurrentThread.ManagedThreadId.ToString(); });
                Console.WriteLine(task.Result);
    
                Console.WriteLine("主线程结束");
            }

    当在Main方法中调用task.Result的时候,将等待task执行完毕并得到返回值,这里的效果跟调用task.Wait()是一样的,只是多了一个返回值。

            static void Main(string[] args)
            {
                Console.WriteLine("-------主线程启动-------");
                Task<string> task = GetLengthAsync();
                Console.WriteLine("Main方法做其他事情");
                Console.WriteLine("Task返回的值" + task.Result);
                Console.WriteLine("-------主线程结束-------");
                Console.Read();
            }
    
            static async Task<string> GetLengthAsync()
            {
                Console.WriteLine("GetLengthAsync Start");
                string str = await GetStringAsync();
                Console.WriteLine("GetLengthAsync End");
                return str;
            }
    
            static Task<string> GetStringAsync()
            {
                return Task<string>.Run(() => { Thread.Sleep(2000); return "finished"; });
            }

    async用来修饰方法,表明这个方法是异步的,声明的方法的返回类型必须为:void或Task或Task<TResult>。返回类型为Task的异步方法中无需使用return返回值,而返回类型为Task<TResult>的异步方法中必须使用return返回一个TResult的值,如上述Demo中的异步方法返回一个string。await必须用来修饰Task或Task<TResult>,而且只能出现在已经用async关键字修饰的异步方法中。async/await必须成对出现才有意义,假如一个方法声明为async,但却没有使用await关键字,则这个方法在执行的时候就被当作同步方法。

  • 相关阅读:
    教你一招Linux下文本比对方法
    Linux下find与exec的联手干大事
    Linux下Shell日期的格式,你知道几种?
    Linux下Python3.6的安装及避坑指南
    多线程中使用CompletableFuture
    ElasticSearch7.6.2中语法使用(更新中)
    ElasticSearch7.6.2使用_update_by_query语法
    ElasticSearch7.6.2使用_delete_by_query产生版本冲突问题
    filebeat7.6.2进程运行一段时间后自动退出问题解决
    把本地项目提交到gitLab
  • 原文地址:https://www.cnblogs.com/5ishare/p/5990970.html
Copyright © 2011-2022 走看看