• .NET 多线程 Task async await


    多线程概念

    两个名词

    线程不安全:多个线程访问同一段代码,产生不确定结果(冲突)

    线程安全:各个线程正常且正确执行,不会出现数据污染等意外

    多线程的例子

    例1:两个线程同时打印

            static void Main(string[] args)
            {
                Method1();
                Method2();
                Console.WriteLine(" main end ");
                Console.ReadKey();
            }
    
            public static async Task Method1()
            {
                await Task.Run(() =>
                {
                    for (int i = 0; i < 50; i++)
                    {
                        Task.Delay(500).Wait();
                        Console.WriteLine(" Method 1");
                    }
                });
            }
    
            public static void Method2()
            {
                for (int i = 0; i < 20; i++)
                {
                    Task.Delay(1000).Wait();
                    Console.WriteLine(" Method 2");
                }
            }

    输出

     例子2:存在依赖支线线程的主线程

    Method3 需要一个从 Method1 返回来的 int 数,用 await 等待返回的结果。

            static void Main(string[] args)
            {
                callMethod();
                Console.ReadKey();
            }
    
            public static async void callMethod()
            {
                Task<int> task = Method1();
    
                Method2();
                int count = await task; //或者写 task.Result; //主线程会停在这一步
                Console.WriteLine("call end");
    
                Method3(count);
            }
    
            public static async Task<int> Method1()
            {
                int count = 0;
                await Task.Run(() =>
                {
                    for (int i = 0; i < 50; i++)
                    {
                        Task.Delay(100).Wait();
                        Console.WriteLine(" Method 1");
                        count += 1; 
                    }
                });
                return count;
            }
    
            public static void Method2()
            {
                for (int i = 0; i < 20; i++)
                {
                    Task.Delay(200).Wait();
                    Console.WriteLine(" Method 2");
                }
            }
    
            public static void Method3(int count)
            {
                Console.WriteLine("Total count is " + count);
            }

    输出

    Task相关

    官方文档传送门

    Task 开启一个新任务

    开启后台线程:Task.Run() 或者 Task.Factory.StartNew()

    以 Task.Run() 开启一个新任务

    //返回值类型为string
    Task<string> task = Task<string>.Run(() => {
        Thread.Sleep(2000);  //或 Task.Delay(2000).Wait();
        return Thread.CurrentThread.ManagedThreadId.ToString(); 
    });
    //会等到task执行完毕才会输出;
    Console.WriteLine(task.Result); //task.Result 可改成 await task

    Task.Factory.StartNew() 可以使用比 Task.Run() 更多的参数,可以做更多定制(如长时间运行)。 参考传送门

    Task.Factory.StartNew(() =>
    {
        Console.WriteLine("进行 线程" + Thread.CurrentThread.ManagedThreadId);
    }, TaskCreationOptions.LongRunning); //设置线程是长时间运行的,这时线程池就不会等待这个线程回收

     

    注:Task 任务可以通过 CancellationTokenSource 类来取消。

    Task.Wait() 和 await Task

    Task.Wait()  阻塞线程,等待期间,系统不会对其他操作响应

    await Task  等待任务完成,等待期间,系统可以响应其他操作

    Task.Delay() 和 Thread.Sleep()

    参考传送门

    1、Thread.Sleep 是同步延迟,Task.Delay异步延迟。

    2、Thread.Sleep 会阻塞线程,Task.Delay不会。

    3、Thread.Sleep不能取消,Task.Delay可以。

    4. Task.Delay() 比 Thread.Sleep() 消耗更多的资源,但是Task.Delay()可用于为方法返回Task类型;或者根据CancellationToken取消标记动态取消等待

    5. Task.Delay() 实质创建一个运行给定时间的任务, Thread.Sleep() 使当前线程休眠给定时间。

    有条件的 Task

    Task 内部提供多种多样的基于队列的链式任务管理方法,通过使用这些快捷方式,可以让异步队列有序的执行,比如 ContinueWith(),ContinueWhenAll(),ContinueWhenAny(),WaitAll(),WaitAny(),WhenAll(),WhenAny()

    Task.WaitAll(t1, t2)  等待多个线程

    Task.WaitAny(t1, t2)  等待任意一个线程

    Task.WhenAll(t1, t2)  创建一个任务,任务会在集合中的所有 Task 对象都完成时完成(不会主动等待)

    var tasks = new List<Task>();
    tasks.Add(Task.Run( () => { Task.Delay(1000).Wait(); Console.WriteLine("1"); } ));
    tasks.Add(Task.Run( () => { Task.Delay(2000).Wait(); Console.WriteLine("2"); } ));
    Task t = Task.WhenAll(tasks);
    t.Wait();
    Console.WriteLine("3");

    这里的输出顺序为:

    1
    2
    3

    Task.WhenAny(t1, t2)  任一任务完成时,创建将完成的任务(返回第一项完成的任务)。 

    var tasks = new List<Task>();
    tasks.Add(Task.Run( () => { Task.Delay(1000).Wait(); Console.WriteLine("1"); } ));
    tasks.Add(Task.Run( () => { Task.Delay(2000).Wait(); Console.WriteLine("2"); } ));
    Task t = Task.WhenAny(tasks);
    t.Wait();
    Console.WriteLine("3");

    这里的输出顺序为:

    1
    3
    2

    async 和 await 异步编程

    1、凡是使用 await 关键字的方法,都必须打上 async 标记

    2、async 标识方法内有异步方法,调用 async 方法,会立刻另起线程执行

    3、await 只是显示等待线程结束:await 表示等待异步方法执行完,并取返回值

    参考来源

    https://www.cnblogs.com/doforfuture/p/6293926.html (Mr靖 的 C#中 Thread,Task,Async/Await,IAsyncResult 的那些事儿!)

    https://www.cnblogs.com/zhao123/p/9999607.html (凌风95 的 C# Task.Run 和 Task.Factory.StartNew 区别)

    https://www.cnblogs.com/yy1234/p/8073732.html (禅道 的 Task.Delay() 和 Thread.Sleep() 区别)

    https://www.cnblogs.com/ma8023/p/11677394.html (逆骨苍狼 的 C# 中的Async 和 Await 的用法详解)

    https://www.cnblogs.com/wangwust/p/9474786.html (wangwust 的 【.NET】- async await 异步编程)

    https://www.cnblogs.com/viter/p/10201228.html (Ron Liang 的 Asp.Net Core 轻松学-多线程之Task快速上手)

  • 相关阅读:
    Nginx从安装到配置文件详解
    python流程控制语句
    python数据类型以及方法
    python介绍以及基础基础语法
    new 操作符
    js 模拟substr
    js 对于链式加载的思考
    js 实现哈夫曼树
    js实现深度优先
    js 广度优先遍历
  • 原文地址:https://www.cnblogs.com/clis/p/14253537.html
Copyright © 2020-2023  润新知