我们知道,每个应用程序就是一个进程,一个进程有多个线程。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. 理解 Memory barrier(内存屏障)【转】

    转自:http://name5566.com/4535.html 参考文献列表:http://en.wikipedia.org/wiki/Memory_barrierhttp://en.wikiped ...

  2. docker 构建带健康检查的redis镜像

    =============================================== 2018/11/5_第1次修改                       ccb_warlock == ...

  3. ssh隐藏的sftp功能的使用

    sftp是Secure File Transfer Protocol的缩写,安全文件传送协议.可以为传输文件提供一种安全的加密方法.sftp 与 ftp 有着几乎一样的语法和功能.SFTP 为 SSH ...

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

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

  5. **PHP二维数组遍历时同时赋值

    php 二维数组遍历赋值 我个人在项目中的写法: //遍历二维数组foreach($tmp_array as $key => $value){ //动态生成图片的URL $attach_url ...

  6. USING NHIBERNATE WITH MySQL

    In previous USING NHIBERNATE WITH SQLITE, we connect SQLITE with ORM framework NHibernate. One of th ...

  7. 切换Intellij ieda 调试为Visual Studio风格

  8. 【LOJ】#2567. 「APIO2016」划艇

    题解 显然有个很暴力的dp,\(dp[i][j]\)表示选到第\(i\)个数,末尾的数是\(j\)的方案数 但是第二维就开不下了,怎么办呢 考虑离散化整个区间,我们记录\(dp[i][j][k]\)表 ...

  9. Storm集群启动流程分析

    Storm集群启动流程分析 程序员 1.客户端运行storm nimbus时,会调用storm的python脚本,该脚本中为每个命令编写了一个方法,每个方法都可以生成一条相应的Java命令. 命令格式 ...

  10. 全局查询文件linux

    在工作中,可能突然需要找到某个文件,这个又不知道,需要全局查询一下. 下面是命令行: find / -name "*.log" | xargs grep "elk&quo ...