专业网站建设品牌,十四年专业建站经验,服务6000+客户--广州京杭网络
免费热线:400-683-0016      微信咨询  |  联系我们

C#异步多线程之TASK

当前位置:网站建设 > 技术支持
资料来源:网络整理       时间:2023/2/14 0:32:33       共计:3624 浏览

简介

TASK首次引入.net Framework 4中,Task对象通常是以异步方式执行于线程池上,是基于ThreadPool的,您可以使用 Status 属性,以及 IsCanceled,IsCompleted和 IsFaulted 属性,以确定任务的状态,Task是目前最为推崇的多线程方法

Task的启动方式

                //常规启动

                Task.Run(() => DoSomeThing());

                //也可以用其构造函数启动

                new Task(() => DoSomeThing()).Start();

                //工厂方式启动

                Task.Factory.StartNew(() => DoSomeThing());

               以上几种启动方式没有什么优劣差别

waitAny waitAll

    #region waitAny waitAll

            {

                //动物界举办了第二届赛跑比赛,参赛的有兔子,乌龟,老虎,大象,长颈鹿

                Console.WriteLine("动物界举办了第二届赛跑比赛,参赛的有兔子,乌龟,老虎,大象,长颈鹿");

                List<Task> tasks = new List<Task>();

                tasks.Add(Task.Run(() => Race("兔子")));

                tasks.Add(Task.Run(() => Race("乌龟")));

                tasks.Add(Task.Run(() => Race("老虎")));

                tasks.Add(Task.Run(() => Race("大象")));

                tasks.Add(Task.Run(() => Race("长颈鹿")));

 

                Task.WaitAny(tasks.ToArray());//会阻塞当前线程,等待某一个任务完成,才进入下一行,会卡界面

                Console.WriteLine("第一名产生");

                Task.WaitAll(tasks.ToArray());//阻塞当前线程,等待任务全部完成,会卡界面

            }

            #endregion

 

 

  //赛跑

        public void Race(string animal)

        {

            Console.WriteLine($"{animal}赛号为{Thread.CurrentThread.ManagedThreadId.ToString("00")},已就位");

            long lResult = 0;

            for (int i = 0; i < 1000000000; i++)

            {

                lResult += i;

            }

            Console.WriteLine($"{animal}到达终点");

        }

 

运行结果如下图,那么恭喜乌龟了

值得一提的是 WaitAny, WaitAll也提供了超时等待的Api 如Task.WaitAll(tasks.ToArray(), 1000); 最多等待1s,超时就不等了,-1为无限等待

还有一点就是,WaitAny, WaitAll卡的是运行线程,如果在启动一个Task将WaitAny, WaitAll方法包裹起来,就不会卡界面了,像这样

Task.Run(()={

Task.WaitAny(tasks.ToArray());

})

 

WhenAny WhenAll

WhenAny和WhenAll与WaitAny和WaitAll最大的区别在与一个阻塞主线程,一个不阻塞主线程,那么在waitAny和WhenAll完成之后的动作应该怎么写呢

                Task.WhenAny(tasks.ToArray()).ContinueWith(t =>

                {

                    Console.WriteLine("第一名产生");

                });//不阻塞当前线程

                Task.WhenAll(tasks.ToArray()).ContinueWith(t =>

                {

                    Console.WriteLine("比赛结束");

                });//不阻塞当前线程

用到了ContinueWith来实现,效果如下图

好吧,再次恭喜乌龟先生又一次拿到了冠军

因为WhenAny,WhenAll 它的返回值是一个Task,所以当某些时候需要调整执行顺序时,将方法加入TaskList中,再用WaitAny,WaitAll即可

Delay

延迟,和Thread有点像,但不一样

下面是Thread 2秒钟

{

                Stopwatch stopwatch = new Stopwatch();

                stopwatch.Start();

                Thread.Sleep(2000);

                stopwatch.Stop();

                Console.WriteLine(stopwatch.ElapsedMilliseconds);

            }

运行结果:

下面是delay

  Stopwatch stopwatch = new Stopwatch();

                stopwatch.Start();

                Task.Delay(2000).ContinueWith(t =>

                {

                    stopwatch.Stop();

                    Console.WriteLine(stopwatch.ElapsedMilliseconds);

                });

运行结果:

通过这两次对比,不难看出,Thread会卡住当前线程,delay不卡线程,只是可以等待一些时间,再去完成一些事情

并行编程(Parallel) 

  Console.WriteLine($"---------开始Parallel编程,线程id{Thread.CurrentThread.ManagedThreadId.ToString("00")}---------");

            Parallel.Invoke(() => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString("00")); }

                   , () => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString("00")); }

                   , () => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString("00")); });

            Console.WriteLine($"---------结束Parallel编程{Thread.CurrentThread.ManagedThreadId.ToString("00")}---------");

通过结果我们发现主线程参与了计算,算是节约了一个线程吧

还有遍历方法如下

Parallel.For(0, 5, i => Race("兔子" + i.ToString()));

有for,肯定有foreach

Parallel.ForEach(new int[] { 1, 2, 3, 4, 5 }, i => Race("兔子" + i.ToString()));

Parallel还有一个重要方法是可以控制并发数量

ParallelOptions options = new ParallelOptions();

                options.MaxDegreeOfParallelism = 3;

                Parallel.For(0, 10, options, i => Race("兔子" + i.ToString()));

运行结果为:

通过运行结果,可以看到程序始终只有3个线程在跑

写完!荆轲刺秦王

版权说明:
本网站凡注明“广州京杭 原创”的皆为本站原创文章,如需转载请注明出处!
本网转载皆注明出处,遵循行业规范,如发现作品内容版权或其它问题的,请与我们联系处理!
欢迎扫描右侧微信二维码与我们联系。
·上一条:配置本地开发机器虚拟域名以及泛域名解析 | ·下一条:C#教程之Threads(异步和多线程)

Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有    粤ICP备16019765号 

广州京杭网络科技有限公司 版权所有