我们知道,每个应用程序就是一个进程,一个进程有多个线程。Task Parallel Library为我们的异步编程、多线程编程提供了强有力的支持,它允许一个主线程运行的同时,另外的一些线程或Task也同时运行。本篇体验基本用法。

基本用法

Taks的构造函数接收的类型是Action,也就是一个委托。

        static void Main(string[] args)
        {
            var t1 = new Task(() =>
            {
                Console.WriteLine("任务1开始");
                Thread.Sleep(1000);
                Console.WriteLine("任务1结束");
            });
            t1.Start();
            Console.ReadKey();
        }

如果把方法放到外面。

        static void Main(string[] args)
        {
            var t1 = new Task(() => DoSth(1,2000));
            t1.Start();
            Console.ReadKey();
        }

        static void DoSth(int id, int sleepTime)
        {
            Console.WriteLine("任务{0}开始",id);
            Thread.Sleep(sleepTime);
            Console.WriteLine("任务{0}结束",id);
        }

如果有多个Task同时执行。

        static void Main(string[] args)
        {
            var t1 = new Task(() => DoSth(1,2000));
            t1.Start();

            var t2 = new Task(() => DoSth(2, 1500));
            t2.Start();

            var t3 = new Task(() => DoSth(3, 3000));
            t3.Start();
            Console.ReadKey();
        }

如果有很多Task,每个Task手动启动的话很费事,Task Parallel Library为我们准备了Task工厂。

        static void Main(string[] args)
        {
            var t1 = Task.Factory.StartNew(() => DoSth(1, 2000));
            var t2 = Task.Factory.StartNew(() => DoSth(2, 1500));
            var t3 = Task.Factory.StartNew(() => DoSth(3, 3000));

            Console.ReadKey();
        }

如果我们想在一个任务结束之后立即执行某个任务,可以使用ContinueWith方法。

        static void Main(string[] args)
        {
            var t1 = Task.Factory.StartNew(() => DoSth(1, 2000)).ContinueWith((pre)=> DoOtherThing(4,2000));
            var t2 = Task.Factory.StartNew(() => DoSth(2, 1500));
            var t3 = Task.Factory.StartNew(() => DoSth(3, 3000));

            Console.ReadKey();
        }

        static void DoSth(int id, int sleepTime)
        {
            Console.WriteLine("任务{0}开始",id);
            Thread.Sleep(sleepTime);
            Console.WriteLine("任务{0}结束",id);
        }

        static void DoOtherThing(int id, int sleepTime)
        {
            Console.WriteLine("其他任务{0}开始", id);
            Thread.Sleep(sleepTime);
            Console.WriteLine("其他任务{0}结束", id);
        }

如果希望等待所有的Task执行完毕,使用WaitAll方法。

        static void Main(string[] args)
        {
            var t1 = Task.Factory.StartNew(() => DoSth(1, 2000));
            var t2 = Task.Factory.StartNew(() => DoSth(2, 1500));
            var t3 = Task.Factory.StartNew(() => DoSth(3, 3000));

            var taskList = new List<Task> {t1, t2, t3};
            Task.WaitAll(taskList.ToArray());
            Console.WriteLine("我是在所有Task执行完毕后才执行的");

            Console.ReadKey();
        }

如果想手动取消结束某个Task,需要为方法带上CancellationToken类型参数。

        static void Main(string[] args)
        {
            var source = new CancellationTokenSource();
            try
            {
                var t1 =
                    Task.Factory.StartNew(() => DoSth(1, 1000, source.Token))
                        .ContinueWith((pre) => DoOtherThing(2, 2000));
                source.Cancel();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.GetType());
            }
            Console.WriteLine("haha");
            Console.ReadKey();
        }

        static void DoSth(int id, int sleepTime, CancellationToken token)
        {
            if (token.IsCancellationRequested)
            {
                Console.WriteLine("任务被取消");
                token.ThrowIfCancellationRequested();
            }

            Console.WriteLine("任务{0}开始",id);
            Thread.Sleep(sleepTime);
            Console.WriteLine("任务{0}结束",id);
        }

        static void DoOtherThing(int id, int sleepTime)
        {
            Console.WriteLine("其他任务{0}开始", id);
            Thread.Sleep(sleepTime);
            Console.WriteLine("其他任务{0}结束", id);
        }

如何从Task从获取方法的返回结果呢?

        static void Main(string[] args)
        {
            Console.WriteLine("开始计算");
            Task<int> t = Task.Factory.StartNew(() => Sum(1, 2));
            Console.WriteLine("等待结果");
            Console.WriteLine(t.Result);
            Console.ReadKey();
        }

        static int Sum(int a, int b)
        {
            return a + b;
        }

后面一个Task获取前面一个Task的返回值。

        static void Main(string[] args)
        {
            Task<string> firstTask = Task.Factory.StartNew<string>(() =>
            {
                Console.WriteLine("第一个任务开始");
                return "hi from the one";
            });

            Task secondTask = firstTask.ContinueWith((prevoursTask) =>
            {
                Console.WriteLine("这里是第二个任务,获取到第一个任务的返回值是{0}",prevoursTask.Result,TaskContinuationOptions.OnlyOnRanToCompletion);
            });
            secondTask.Wait();
            Console.ReadKey();
        }

等待所有Task完成。

        static void Main(string[] args)
        {
           var t1 =  Task.Factory.StartNew(() =>
            {
                Console.WriteLine("第一个任务");
                Thread.Sleep(1000);
            });

            var t2 = Task.Factory.StartNew(() =>
            {
                Console.WriteLine("第二个任务");
                Thread.Sleep(1000);
            });

            var taskList = new List<Task> {t1, t2};

            Task.Factory.ContinueWhenAll(taskList.ToArray(), (t) => { Console.WriteLine("所有任务完成我就出来"); });

            Console.ReadKey();
        }

如果是嵌套Task。

        static void Main(string[] args)
        {
            Task.Factory.StartNew(() =>
            {
                Task child = Task.Factory.StartNew(() =>
                {
                    Console.WriteLine("我是子任务");
                }, TaskCreationOptions.AttachedToParent);
            }).Wait();
            Console.ReadKey();
        }

启动Task的几种方式

1、通过Task.Factory.StartNew方法。

        static void Main(string[] args)
        {
            Task.Factory.StartNew(() => SaySth("hello"));
            Console.ReadKey();
        }

        static void SaySth(string msg)
        {
            Console.WriteLine(msg);
        }

2、通过Task的Start实例方法

        static void Main(string[] args)
        {
            var t = new Task(() => SaySth("hello"));
            t.Start();
            Console.ReadKey();
        }

或者干脆用委托。

        static void Main(string[] args)
        {
            Task t = new Task(delegate {SaySth("hello");});
            t.Start();
            Console.ReadKey();
        }

3、Task的静态方法Run

        static void Main(string[] args)
        {
            Task t = Task.Run(() => SaySth("hello"));
            Console.ReadKey();
        }

        static void SaySth(string msg)
        {
            Console.WriteLine(msg);
        }

一个例子

比如说要下载某个页面,在保持当前UI界面无影响的情况下,使用Task在后台启动任务下载某个页面。

        static void Main(string[] args)
        {
            Console.WriteLine("界面内容");
            Task<string> r = DownloadAsync("http://www.baidu.com");
            while (!r.IsCompleted)
            {
                Console.Write(".");
                Thread.Sleep(250);
            }
            Console.WriteLine(r.Result);
            Console.ReadKey();
        }

        private static string DownloadWebPage(string url)
        {
            WebRequest request = WebRequest.Create(url);
            WebResponse response = request.GetResponse();
            var reader = new StreamReader(response.GetResponseStream());
            return reader.ReadToEnd();
        }

        private static Task<string> DownloadAsync(string url)
        {
            return Task.Factory.StartNew(() => DownloadWebPage(url));
        }

Task Parallel Library01,基本用法的更多相关文章

  1. TPL(Task Parallel Library)多线程、并发功能

    The Task Parallel Library (TPL) is a set of public types and APIs in the System.Threading and System ...

  2. C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是TAP(Task-based Asynchronous Pattern, 基于任务的异步模式)

    学习书籍: <C#本质论> 1--C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是 ...

  3. Using the Task Parallel Library (TPL) for Events

    Using the Task Parallel Library (TPL) for Events The parallel tasks library was introduced with the ...

  4. Winform Global exception and task parallel library exception;

    static class Program { /// <summary> /// 应用程序的主入口点. /// </summary> [STAThread] static vo ...

  5. C#~异步编程再续~大叔所理解的并行编程(Task&Parallel)

    返回目录 并行这个概念出自.net4.5,它被封装在System.Threading.Tasks命名空间里,主要提供一些线程,异步的方法,或者说它是对之前Thread进行的二次封装,为的是让开发人员更 ...

  6. Task Parallel Library02,更进一步

    在前一篇中,了解了Task的基本用法 如果一个方法返回Task,Task<T>,如何获取Task的返回值,获取值的过程会阻塞线程吗? static void Main(string[] a ...

  7. Task/Parallel实现异步多线程

    代码: #region Task 异步多线程,Task是基于ThreadPool实现的 { //TestClass testClass = new TestClass(); //Action<o ...

  8. 异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource

    1 进程-线程-多线程,同步和异步2 异步使用和回调3 异步参数4 异步等待5 异步返回值 5 多线程的特点:不卡主线程.速度快.无序性7 thread:线程等待,回调,前台线程/后台线程, 8 th ...

  9. Task.Factory.StartNew的用法

    代码: private void button5_Click(object sender, EventArgs e) { ; Task.Factory.StartNew(() => { Mess ...

随机推荐

  1. PHPStorm 配置本地服务器

    本篇教程为配置 PHPStorm 本地服务器,以方便程序调试. 本地服务器工具:XAMPP for windows 7.1.1-0 / Apache 2.4.25 ( Win32 ) / PHP 7. ...

  2. sysbench安装及性能测试

    现在的压力测试工具各种各样,只要上手好几款功能强大点的而且比较大众化的压力测试工具即可,以下跟大家交流下sysbench的安装和压力测试 sysbench支持以下几种测试模式: 1.CPU运算性能 2 ...

  3. NOIP 2000 计算器的改良

    题面 NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手ZL先生. 为 ...

  4. 4.类型设计规范《.NET设计规范》

    类是引用类型的一般情况,占了框架中的大多情况,类的流行归于它支持面向对象的特征,以及它的普遍的适用性,基类和抽象类是两个特殊的逻辑分组,它们与扩张性有关. 由于CLR不支持多继承,接口类型可以用来模拟 ...

  5. Java 构造 BSON 数据类型

    Java 构造 BSON 数据类型 整数/符浮点数 Java BSON 构造整数/符浮点数类型 // {a:123, b:3.14} BSONObject obj = new BasicBSONObj ...

  6. Docker 图形化页面管理工具使用

    一.Docker图形化工具 docker 图形页面管理工具常用的有三种,DockerUI ,Portainer ,Shipyard .DockerUI 是 Portainer 的前身,这三个工具通过d ...

  7. form表单自动提交

    form表单提交是web项目中经常遇到的,但是如果form中只有一个input为text类型的输入框时, 需要格外注意,因为这时候只要你按下回车键,form表单就会自动提交,这是form表单的一个特性 ...

  8. java线程中断的办法

    目录 中断线程相关的方法 中断线程 for循环标记退出 阻塞的退出线程 使用stop()方法停止线程 中断线程相关的方法 中断线程有一些相应的方法,这里列出来一下. 注意,如果是Thread.meth ...

  9. AI技术在智能海报设计中的应用

    背景 在视觉设计领域中,设计师们往往会因为一些简单需求付出相当多的时间,比如修改文案内容,设计简单的海报版式,针对不同机型.展位的多尺寸拓展等.这些工作需要耗费大量的时间.人力成本(5~6张/人日), ...

  10. Windows栈溢出原理

    1.栈是什么? 栈是一种运算受限的线性表 其限制是仅允许在表的一端进行插入和删除运算 这一端称为栈顶(TOP),相对的另一端称为栈底(BASE) 向一个栈插入新元素,称作进栈.入栈或压栈(PUSH) ...