42-异步

Task

任务,背后的实现也是使用了线程池线程,但它的性能优于ThreadPoll,因为它使用的不是线程池的全局队列,而是使用的本地队列,使线程之间的资源竞争减少。同时Task提供了丰富的API来管理线程、控制。但是相对前面的两种耗内存,Task依赖于CPU对于多核的CPU性能远超前两者,单核的CPU三者(thread、threadpool、Task)的性能没什么差别

class Program
    {
        /// <summary>
        /// 启动方式
        /// </summary>
        public static void StartWay()
        {
            var task1 = new Task(() =>
            {
                Console.WriteLine("Hello,task");
            });
            task1.Start();

            var task2 = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("Hello,task started by task factory");
            });
        }

        /// <summary>
        /// 生命周期测试
        /// </summary>
        public static void LifeCircle()
        {
            var task1 = new Task(() =>
            {
                Console.WriteLine("Begin");
                System.Threading.Thread.Sleep(2000);
                Console.WriteLine("Finish");
            });
            Console.WriteLine("Before start:" + task1.Status);
            task1.Start();
            Console.WriteLine("After start:" + task1.Status);
            task1.Wait();
            Console.WriteLine("After Finish:" + task1.Status);

        }

        /// <summary>
        /// 等待所有任务完成
        /// </summary>
        public static void WaitAll()
        {
            string zhe = "";
            var task1 = new Task(() =>
            {
                Console.WriteLine("Task 1 Begin");
                System.Threading.Thread.Sleep(2000);
                Console.WriteLine("Task 1 Finish");
                zhe = "fswet";
            });
            var task2 = new Task(() =>
            {
                Console.WriteLine("Task 2 Begin");
                System.Threading.Thread.Sleep(3000);
                Console.WriteLine("Task 2 Finish");
            });

            task1.Start();
            task2.Start();
            Task.WaitAll(task1, task2);
            Console.WriteLine("WaitAll task finished!"+ zhe);
            
        }

        /// <summary>
        /// 等待任意一个执行任务完成
        /// </summary>
        public static void WaitAny()
        {
            var task1 = new Task(() =>
            {
                Console.WriteLine("Task 1 Begin");
                System.Threading.Thread.Sleep(2000);
                Console.WriteLine("Task 1 Finish");
            });
            var task2 = new Task(() =>
            {
                Console.WriteLine("Task 2 Begin");
                System.Threading.Thread.Sleep(3000);
                Console.WriteLine("Task 2 Finish");
            });

            task1.Start();
            task2.Start();
            Task.WaitAny(task1, task2);
            Console.WriteLine("WaitAny task finished!");
        }

        /// <summary>
        /// 任务回调方法
        /// </summary>
        public static void ContinueWith()
        {
            var task1 = new Task(() =>
            {
                Console.WriteLine("Task 1 Begin");
                System.Threading.Thread.Sleep(2000);
                Console.WriteLine("Task 1 Finish");
            });
            var task2 = new Task(() =>
            {
                Console.WriteLine("Task 2 Begin");
                System.Threading.Thread.Sleep(3000);
                Console.WriteLine("Task 2 Finish");
            });


            task1.Start();
            task2.Start();
            var result = task1.ContinueWith<string>(task =>
            {
                Console.WriteLine("task1 finished!");
                return "This is task1 result!";
            });

            Console.WriteLine(result.Result.ToString());

            var result2 = task2.ContinueWith<string>(task =>
            {
                Console.WriteLine("task2 finished!");
                return "This is task2 result!";
            });

            Console.WriteLine(result2.Result.ToString());
        }

        /// <summary>
        /// 取消任务
        /// </summary>
        public static void Cancel()
        {
            var tokenSource = new CancellationTokenSource();
            var token = tokenSource.Token;
            var task = Task.Factory.StartNew(() =>
            {
                for (var i = 0; i < 1000; i++)
                {
                    System.Threading.Thread.Sleep(1000);
                    if (token.IsCancellationRequested)
                    {
                        Console.WriteLine("Abort mission success!");
                        return;
                    }
                }
            }, token);
            token.Register(() =>
            {
                Console.WriteLine("Canceled");
            });
            Console.WriteLine("Press enter to cancel task...");
            Console.ReadKey();
            tokenSource.Cancel();

            Console.ReadKey();//这句忘了加,程序退出了,看不到“Abort mission success!“这个提示
        }

        static void Main(string[] args)
        {
            //Console.WriteLine("StartWay is runing");
            //StartWay();

            //Console.WriteLine("LifeCircle is runing");
            //LifeCircle();
            //Console.WriteLine("WaitAll is runing");
            WaitAll();
            //Console.WriteLine("WaitAny is runing");
            //WaitAny();
            //Console.WriteLine("ContinueWith is runing");
            //ContinueWith();
            //Console.WriteLine("Cancel is runing");
            //Cancel();

            Console.Read();

        }
    }

.Net 提供了3中异步编程模型

  • TAP(基于任务的异步模式):使用单一方法表示异步操作的开始和结束,是.Net中进行异步编程的推荐方法。(.Net Framework 4中引入的)
  • EAP(基于事件的异步模式):提供异步行为的基于事件的旧模型。 这种模式需要后缀为 Async 的方法,以及一个或多个事件、事件处理程序委托类型和 EventArg 派生类型。 EAP 是在 .NET Framework 2.0 中引入的。 不建议新的开发使用此模式。
  • APM(异步编程模型):(也称为 IAsyncResult 模式),这是使用 IAsyncResult 接口提供异步行为的旧模型。 在这种模式下,同步操作需要 Begin 和 End 方法(例如,BeginWrite 和 EndWrite以实现异步写入操作)。 不建议新的开发使用此模式。

TAP(基于任务的异步模式)

C# 异步编程的核心是 Task 和 Task 对象(深入了解Task和Task),这两个对象对异步操作建模。它们受关键字 async 和 await 的支持(二者是异步编程的核心关键字)。通过这两个关键字,可以使用 .NET Framework、.NET Core 或 Windows 运行时中的资源,轻松创建异步方法(几乎与创建同步方法一样轻松)。 使用 async 关键字定义的异步方法简称为“异步方法”。await 关键字控制执行 await 的方法的调用方,且它最终允许 UI 具有响应性或服务具有灵活性。

async是用来修饰方法,表示此方法可以是异步方法,如果方法里不包含await,则此方法相当于普通的同步方法。
await是使用在被async修饰的方法里。

await 后面跟上一个异步操作Task,当程序执行到此行代码时,由于有await的修饰,会等待异步操作Task执行,Task执行完成后才会执行此方法里await这一行后面的代码,

但是外部调用async方法的地方,不会等待Task完成,就执行后面的代码。

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main function begin...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            Test();
            Console.WriteLine("Main function end");
            Console.ReadLine();
        }
 
        public static async  void Test()
        {
            Console.WriteLine("test begin...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            await Task.Run(()=>{ Work1(); });
            await Task.Run(() => { Work2(); });
            await Task.Run(() => { Work3(); });
             Console.WriteLine("test end---");
        }
 
        public static void Work1()
        {
            Console.WriteLine("Work1 start...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            Thread.Sleep(6000);
            Console.WriteLine("Work1 end---");
        }
 
        public static void Work2()
        {
            Console.WriteLine("Work2 start...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            Thread.Sleep(6000);
            Console.WriteLine("Work2 end---");
        }
 
        public static void Work3()
        {
            Console.WriteLine("Work3 start...CurrentThread ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            Thread.Sleep(6000);
            Console.WriteLine("Work3 end---");
        }
    }

在这里插入图片描述

从测试结果,可以看出,Test方法还没有执行结束,Main方法里调用Test方法这一行后面的代码,已经执行,无需等待Test方法。

Test方法由于被async修饰,表明这个可以是异步方法,方法内部await修饰的Task,执行到这一行代码时,会等待Task执行完成后,才会执行Test方法里下一行的代码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值