C#异步编程Task的创建方式

一、简介

ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便。比如:
Task支持线程的取消、完成、失败通知等交互性操作,但是ThreadPool不支持;
Task支持线程执行的先后次序,但是ThreadPool不支持;;
以往,如果开发者要实现上述功能,需要完成很多额外的工作,现在,FCL中提供了一个功能更强大的概念:Task。Task在线程池的基础上进行了优化,并提供了更多的API。在FCL4.0中,如果我们要编写多线程程序,Task显然已经优于传统的方式。

            Task t = new Task(() =>
            {
                Console.WriteLine("Start……");
                //模拟工作过程
                Thread.Sleep(5000);
            });
            t.Start();
            t.ContinueWith((task) =>
            {
                Console.WriteLine("Already Finished,States:");
                Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
            });
            Console.ReadKey();

二、Task创建

无返回值创建方式

线程引用方法:

        static void TaskMethod(string name)
        {
            Console.WriteLine("Task: {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }

方式一:

            //方式一
            var t1 = new Task(() => TaskMethod("Task_1"));
            t1.Start();
            //等待所有任务结束
            //任务的状态:
            //Start之前为:Created
            //Start之后为:WaitingToRun
            Task.WaitAll(t1);////等待所有任务结束

方式二:

            //方式二
            Task.Run(() => TaskMethod("Task_2"));

方式三:

            //方式三
            Task.Factory.StartNew(() => TaskMethod("Task_3")); //直接异步的方法
             //或者
            var t3 = Task.Factory.StartNew(() => TaskMethod("Task_3"));
            Task.WaitAll(t3);//等待所有任务结束
            //任务的状态
            //Start之前为:Running
            //Start之后为:Running

实例:

    class Program
    {
        static void Main(string[] args)
        {
            var t1 = new Task(() => TaskMethod("Task_1"));
            var t2 = new Task(() => TaskMethod("Task_2"));
            t2.Start();
            t1.Start();
            Task.WaitAll(t1, t2);
            Task.Run(() => TaskMethod("Task_3"));
            Task.Factory.StartNew(() => TaskMethod("Task_4"));
            //标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。
            Task.Factory.StartNew(() => TaskMethod("Task_5"), TaskCreationOptions.LongRunning);

            #region 常规的使用方式
            Console.WriteLine("主線程執行業務處理.");
            //创建任务
            Task task = new Task(() =>
            {
                Console.WriteLine("使用System.Threading.Tasks.Task執行異步操作.");
                for (int i = 0; i < 10; i++)
                {
                    Console.WriteLine(i);
                }
            });
            //启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
            task.Start();
            Console.WriteLine("主線程執行其他處理");
            task.Wait();
            #endregion

            Thread.Sleep(TimeSpan.FromSeconds(1));
            Console.ReadLine();
        }

        static void TaskMethod(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
        }
    }

结果:

async/await的实现方式:

    class Program
    {
        async static void AsyncFunction()
        {
            await Task.Delay(1);
            Console.WriteLine("使用System.Threading.Tasks.Task執行異步操作.");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("AsyncFunction:i={0}", i));
            }
        }

        public static void Main()
        {
            Console.WriteLine("主線程執行業務處理.");
            AsyncFunction();
            Console.WriteLine("主線程執行其他處理");
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(string.Format("Main:i={0}", i));
            }
            Console.ReadLine();
        }
    }

结果:

带返回值方式

线程引用方法

        static Task<int> CreateTask(string name)
        {
            return new Task<int>(() => TaskMethod1(name));
        }
        static int TaskMethod1(string name)
        {
            Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(2));
            return 42;
        }

方式四:

            //方式四
            Task<int> task = CreateTask("Task_1");
            task.Start();
            int result = task.Result;

实例:

    class Program
    {
        static Task<int> CreateTask(string name)
        {
            return new Task<int>(() => TaskMethod(name));
        }

        static void Main(string[] args)
        {
            TaskMethod("Main Thread Task");
            Task<int> task = CreateTask("Task_1");
            task.Start();
            int result = task.Result;
            Console.WriteLine("Task_1 Result is: {0}", result);

            task = CreateTask("Task_2");
            //该任务会运行在主线程中
            task.RunSynchronously();
            result = task.Result;
            Console.WriteLine("Task_2 Result is: {0}", result);

            task = CreateTask("Task_3");
            Console.WriteLine(task.Status);
            task.Start();

            while (!task.IsCompleted)
            {
                Console.WriteLine(task.Status);
                Thread.Sleep(TimeSpan.FromSeconds(0.5));
            }

            Console.WriteLine(task.Status);
            result = task.Result;
            Console.WriteLine("Task_3 Result is: {0}", result);

            #region 常规使用方式
            //创建任务
            Task<int> getsumtask = new Task<int>(() => Getsum());
            //启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
            getsumtask.Start();
            Console.WriteLine("主線程執行其他處理");
            //等待任务的完成执行过程。
            getsumtask.Wait();
            //获得任务的执行结果
            Console.WriteLine("任務執行結果:{0}", getsumtask.Result.ToString());
            Console.ReadLine();
            #endregion
        }

        static int TaskMethod(string name)
        {
            Console.WriteLine("Task: {0} is running on a thread id {1}. Is thread pool thread: {2}",
                name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(TimeSpan.FromSeconds(2));
            return 42;
        }

        static int Getsum()
        {
            int sum = 0;
            Console.WriteLine("使用Task執行異步操作.");
            for (int i = 0; i < 100; i++)
            {
                sum += i;
            }
            return sum;
        }
    }

结果:

async/await的实现:

    class Program
    {
        public static void Main()
        {
            var ret1 = AsyncGetsum();
            Console.WriteLine("主線程執行其他處理");
            for (int i = 1; i <= 3; i++)
                Console.WriteLine("Call Main()");
            int result = ret1.Result;                  //阻塞主线程
            Console.WriteLine("任務執行結果:{0}", result);
            Console.ReadLine();
        }

        async static Task<int> AsyncGetsum()
        {
            await Task.Delay(1);
            int sum = 0;
            Console.WriteLine("使用Task執行異步操作.");
            for (int i = 0; i < 100; i++)
            {
                sum += i;
            }
            return sum;
        }
    }

结果:

到此这篇关于C#创建异步Task的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#如何使用Task执行异步操作

    为什么要使用 Task 线程是创建并发的底层工具,因此具有一定的局限性. 没有简单的方法可以从联合(Join)线程得到"返回值".因此必须创建一些共享域.当抛出一个异常时,捕捉和处理异常也是麻烦的. 线程完成之后,无法再次启动该线程.相反,只能联合(Join)它(在进程阻塞当前线程). 任务是可组合的--使用延续将它们串联在一起.它们可以使用线程池减少启动延迟,而且它们可以通过TaskCompletionSource使用回调方法,避免多个线程同时等待I/O密集操作. Task 和 Th

  • c# 使用Task实现非阻塞式的I/O操作

    在前面的<基于任务的异步编程模式(TAP)>文章中讲述了.net 4.5框架下的异步操作自我实现方式,实际上,在.net 4.5中部分类已实现了异步封装.如在.net 4.5中,Stream类加入了Async方法,所以基于流的通信方式都可以实现异步操作. 1.异步读取文件数据 public static void TaskFromIOStreamAsync(string fileName) { int chunkSize = 4096; byte[] buffer = new byte[chu

  • 深入分析C# Task

    ​Task的MSDN的描述如下: [Task类的表示单个操作不会返回一个值,通常以异步方式执行. Task对象是一种的中心思想基于任务的异步模式首次引入.NETFramework 4 中. 因为由执行工作Task对象通常以异步方式执行线程池线程上而不是以同步方式在主应用程序线程中,可以使用Status属性,并将IsCanceled, IsCompleted,和IsFaulted属性,以确定任务的状态. 大多数情况下,lambda 表达式用于指定该任务所执行的工作量. 对于返回值的操作,您使用Ta

  • C# 并行和多线程编程——Task进阶知识

    一.Task的嵌套 Task中还可以再嵌套Task,Thread中能不能这样做,我只能说我是没这样写过.Task中的嵌套,我感觉其实也可以分开来写,不过嵌套起来会方便管理一点.Task中的嵌套分为两种,关联嵌套和非关联嵌套,就是说内层的Task和外层的Task是否有联系,下面我们编写代码先来看一下非关联嵌套,及内层Task和外层Task没有任何关系,还是在控制台程序下面,代码如下: static void Main(string[] args) { var pTask = Task.Factor

  • C# task应用实例详解

    Task的应用 ​Task的MSDN的描述如下: [Task类的表示单个操作不会返回一个值,通常以异步方式执行. Task对象是一种的中心思想基于任务的异步模式首次引入.NETFramework 4 中. 因为由执行工作Task对象通常以异步方式执行线程池线程上而不是以同步方式在主应用程序线程中,可以使用Status属性,并将IsCanceled, IsCompleted,和IsFaulted属性,以确定任务的状态. 大多数情况下,lambda 表达式用于指定该任务所执行的工作量. 对于返回值的

  • 基于c# Task自己动手写个异步IO函数

    前言 对于服务端,达到高性能.高扩展离不开异步.对于客户端,函数执行时间是1毫秒还是100毫秒差别不大,没必要为这一点点时间煞费苦心.对于异步,好多人还有误解,如: 异步就是多线程:异步就是如何利用好线程池.异步不是这么简单,否则微软没必要在异步上花费这么多心思.本文就介绍异步最新的实现方式:Task,并自己动手写一个异步IO函数.只有了解了异步函数内部实现方式,才能更好的利用它. 对于c#,异步处理经过了多个阶段,但是对于现阶段异步就是Task,微软用Task来抽象异步操作.以后的异步函数,处

  • C#利用Task实现任务超时多任务一起执行的方法

    前言 其实Task跟线程池ThreadPool的功能类似,不过写起来更为简单,直观.代码更简洁了,使用Task来进行操作.可以跟线程一样可以轻松的对执行的方法进行控制. 创建Task有两种方式,一种是使用构造函数创建,另一种是使用 Task.Factory.StartNew 进行创建. 如下代码所示 1.使用构造函数创建Task Task t1 = new Task(MyMethod); 2.使用Task.Factory.StartNew 进行创建Task Task t1 = Task.Fact

  • C#中Task.Yield的用途深入讲解

    前言 最近在阅读 .NET Threadpool starvation, and how queuing makes it worse这篇博文时发现文中代码中的一种 Task 用法之前从未见过,在网上看了一些资料后也是云里雾里不知其解,很是困扰.今天在程序员节的大好日子里终于想通了,于是写下这篇随笔分享给大家,也过过专心写博客的瘾. 这种从未见过的用法就是下面代码中的 await Task.Yield() : static async Task Process() { await Task.Yi

  • C#多线程编程Task用法详解

    目录 一.基本概念 Task优势 二.Task用法 创建任务 1.使用Task创建无返回值 2.使用Task.Run方法创建任务 3.使用Factory方式创建任务 4.创建带返回值的Task 三.常见方法 1.WaitAll() 2.WaitAny() 3.ContinueWhenAll() 4.ContinueWhenAny 5.ContinueWith 一.基本概念 Task优势 ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便,例

  • C# 并行和多线程编程——认识和使用Task

    对于多线程,我们经常使用的是Thread.在我们了解Task之前,如果我们要使用多核的功能可能就会自己来开线程,然而这种线程模型在.net 4.0之后被一种称为基于"任务的编程模型"所冲击,因为task会比thread具有更小的性能开销,不过大家肯定会有疑惑,任务和线程到底有什么区别呢? 任务和线程的区别: 1.任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行. 2.任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线

  • C#关于Task.Yeild()函数的讨论

    在与同事讨论async/await内部实现的时候,突然想到Task.Yeild()这个函数,为什么呢,了解一点C#async/await内部机制的都知道,在await一个异步任务(函数)的时候,它会先判断该Task是否已经完成,如果已经完成,则继续执行下去,不会返回到调用方,原因是尽量避免线程切换,因为await后面部分的代码很可能是另一个不同的线程执行,而Task.Yeild()则可以强制回到调用方,或者说主动让出执行权,给其他Task执行的机会,可以把Task理解为协程,Task.Yeild

  • c#异步task示例分享(异步操作)

    c# Task异步操作 复制代码 代码如下: using System;using System.Threading;using System.Threading.Tasks; namespace ConsoleApplication18{    class Program    {        static void Main(string[] args)        {            Func<string, string> _processTimeFunc = new Fun

随机推荐