我们知道,每个应用程序就是一个进程,一个进程有多个线程。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. Newtonsoft 反序列化字符串

    string json=“[{“name”:”zhangsan”,”age”:”12”},{“name”:”zhangsan”,”age”:”12”}]” 方法1: JArray arr = (JAr ...

  2. js防止sql注入的参数过滤

    js防止sql注入的参数过滤 <script language="javascript"> <!-- var url = location.search; var ...

  3. Java编程的逻辑 (58) - 文本文件和字符流

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  4. IntelliJ IDEA快捷键:Esc

    the Esc key in any tool window moves the focus to the editor. 任何工具窗口都会将焦点移动到编辑器.

  5. GitLab备份的创建与恢复

    使用Gitlab一键安装包安装Gitlab非常简单, 同样的备份恢复与迁移也非常简单. 使用一条命令即可创建完整的Gitlab备份: gitlab-rake gitlab:backup:create使 ...

  6. 【Java】 遍历HashMap

    1.遍历键值对 使用map.entrySet(),注意foreach语句中的类型为Map.Entry<K, V> 2.遍历Key 使用map.keySet() 3.遍历Value 使用ma ...

  7. CUDA安装出现图形驱动程序安装失败

    win7安装cuda9时出现图形驱动程序安装失败,解决办法是右键计算机>管理>服务和应用程序>服务>找到“Windows Installer”,右键选择“启动” 参考自http ...

  8. 007.LVM查看命令

    一 PV查看 [root@kauai ~]# pvdisplay #显示有关物理卷的信息 --- Physical volume --- PV Name /dev/sdb5 #PV名称 VG Name ...

  9. html导出pdf的四种方式

    将html页面导出为pdf文件并打印,可以直接在windows下使用Ctrl + P,苹果下⌘ + P. 如果需要用代码实现,可以考虑jsPDF.iText.wkhtmltopdf等方式. 以下是三种 ...

  10. HashMap分析 + 哈希表

    http://www.cnblogs.com/hzmark/archive/2012/12/24/HashMap.html http://www.cnblogs.com/xqzt/archive/20 ...