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

为什么要使用 Task

线程是创建并发的底层工具,因此具有一定的局限性。

  • 没有简单的方法可以从联合(Join)线程得到“返回值”。因此必须创建一些共享域。当抛出一个异常时,捕捉和处理异常也是麻烦的。
  • 线程完成之后,无法再次启动该线程。相反,只能联合(Join)它(在进程阻塞当前线程)。

任务是可组合的——使用延续将它们串联在一起。它们可以使用线程池减少启动延迟,而且它们可以通过TaskCompletionSource使用回调方法,避免多个线程同时等待I/O密集操作。

Task 和 Thread 区别

1、任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执行。

2、任务跟线程不是一对一的关系,比如开10个任务并不是说会开10个线程,这一点任务有点类似线程池,但是任务相比线程池有很小的开销和精确的控制。

Task和Thread一样,位于System.Threading命名空间下

与线程相比,Task是一个更高级的抽象概念,它标识一个通过或不通过线程实现的并发操作。

Task 介绍

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

Task 简单实现

通过使用Task的构造函数来创建任务,并调用Start方法来启动任务并执行异步操作。

static void Main(string[] args)
{
        Console.WriteLine("主线程执行业务处理.");
        //创建任务
        Task task = new Task(() => {
            Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作.");
            for (int i = 0; i < 10; i++)
            {
                  Console.WriteLine(i);
            }
      });
     //启动任务,并安排到当前任务队列线程中执行任务
      task.Start();
      Console.WriteLine("主线程执行其他处理");
}

从Framework 4.5开始,启动一个由后台线程实现的Task,也可以使用静态方法 Task.Run

Task task = Task.Run(() =>
    {
        Thread.Sleep(2000);
        Console.WriteLine("Foo");
    });

Task默认使用线程池,它们都是后台线程。意味当主线程结束时,所有任务都会随之停止。

Task 执行状态

1.等待(Wait)

调用Wait方法,可以阻塞任务,直至任务完成,效果等同于Thread.Join:

Task task = Task.Run(() =>
    {
        Thread.Sleep(2000);
        Console.WriteLine("Foo");
    });
    Console.WriteLine(task.IsCompleted); //False
    task.Wait();//阻塞,直至任务完成
    Console.WriteLine(task.IsCompleted); //True
    Console.ReadLine();

2. 返回值

Task<TResult>允许任务返回一个值。调用Task.Run,传入一个Func<TResult>代理(或者兼容的Lambda表达式),代替Action,就可以获得一个Task<TResult>:

Task<int> task = Task.Run (() => { Console.WriteLine ("Foo"); return 3; });

int result = task.Result;      // Blocks if not already finished
Console.WriteLine (result);    // 3

下面的例子创建一个任务,它使用LINQ就按前3百万个整数(从2开始)中的素数个数:

Task<int> primeNumberTask = Task.Run(() =>
        Enumerable.Range(2, 3000000).Count(n => Enumerable.Range(2, (int)Math.Sqrt(n) - 1).All(i => n % i > 0)));

    Console.WriteLine("Task running...");
    Console.WriteLine("The answer is " + primeNumberTask.Result);

这段代码会打印“Task running...”,然后几秒钟后打印216815。

3. Task.Delay

Task.Delay是Thread.Sleep的异步版本

Task.Delay(5000).GetAwaiter().OnCompleted(()=>Console.WriteLine(42));

或者

Task.Delay(5000).ContinueWith(ant => Console.WriteLine(42));

以上就是C#如何使用Task执行异步操作的详细内容,更多关于c# 用Task执行异步操作的资料请关注我们其它相关文章!

(0)

相关推荐

  • 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

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

  • 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

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

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

  • c# 几个常见的TAP异步操作

    在本系列上一篇文章 [15:异步编程基础] 中,我们讲到,现代应用程序广泛使用的是基于任务的异步编程模式(TAP),历史的 EAP 和 AMP 模式已经过时不推荐使用.今天继续总结一下 TAP 的异步操作,比如取消任务.报告进度.Task.Yield().ConfigureAwait() 和并行操作等. 虽然实际 TAP 编程中很少使用到任务的状态,但它是很多 TAP 操作机理的基础,所以下面先从任务状态讲起. 1 任务状态 Task 类为异步操作提供了一个生命周期,这个周期由 TaskStat

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

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

  • 简单实现C#异步操作

    在.net4.0以后异步操作,并行计算变得异常简单,但是由于公司项目开发基于.net3.5所以无法用到4.0的并行计算以及Task等异步编程.因此,为了以后更方便的进行异步方式的开发,我封装实现了异步编程框架,通过BeginInvoke.EndInvoke的方式实现异步编程. 一.框架结构 整个框架包括四个部分 1.基类抽象Opeartor 我把每个异步执行过程称为一个Operate,因此需要一个Opeartor去执行 2.FuncAsync 异步的Func 3.ActionAsync 异步的A

  • c#异步操作后台运行(backgroundworker类)示例

    c#异步操作,BackgroundWorker类的使用,可以在后台运行需要的代码逻辑. 复制代码 代码如下: using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading;using System.Windows.Fo

  • C#异步方法返回void与Task的区别详解

    C#异步方法返回void和Task的区别 如果异步(async关键字)方法有返回值,返回类型为T时,返回类型必然是 Task<T>. 但是如果没有返回值,异步方法的返回类型有2种,一个是返回 Task, 一个是返回 void: public async Task CountDownAsync(int count) { for (int i = count; i >= 0; i--) { await Task.Delay(1000); } } public async void Count

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

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

  • C#如何Task执行任务,等待任务完成

    目录 Task执行任务,等待任务完成 C# Task任务队列 需求 基本的Task用法 让Task任务按顺序执行 使用异步委托解决UI界面卡死问题 异步任务队列按顺序执行 封装任务队列 Task执行任务,等待任务完成 代码: //任务 Func<int> Funcs = () => {     Console.WriteLine("任务开始");     return 1 + 1; };   //执行任务 Task<int> printRes = Task

  • 深入分析C# Task

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

  • async/await让异步操作同步执行的方法详解

    一.前言 我们经常会遇到这样的麻烦事,多个函数按顺序执行,返回结果却不是我们预期的顺序,原因一般是由于异步操作引起的,所以呢,我们需要一种解决方案来处理这种问题,从而使得异步操作按照同步的方式来执行,这样我们就可以控制异步操作输出结果的顺序了 二.异步操作会带来什么问题 异步操作可能会许多的问题,下面是常见的两种 1.函数执行的结果并不是按照顺序返回 function fn1(){ console.log(111) setTimeout(function(){ console.log('wait

  • 详解C#中 Thread,Task,Async/Await,IAsyncResult的那些事儿

    说起异步,Thread,Task,async/await,IAsyncResult 这些东西肯定是绕不开的,今天就来依次聊聊他们 1.线程(Thread) 多线程的意义在于一个应用程序中,有多个执行部分可以同时执行:对于比较耗时的操作(例如io,数据库操作),或者等待响应(如WCF通信)的操作,可以单独开启后台线程来执行,这样主线程就不会阻塞,可以继续往下执行:等到后台线程执行完毕,再通知主线程,然后做出对应操作! 在C#中开启新线程比较简单 static void Main(string[]

  • Python 中由 yield 实现异步操作

    yield在python中初学时,觉得比较难理解.yield的作用: ①返回一个值.②接收调用者的参数 分析下面的代码: #!/usr/bin/env python3 # -*- coding:utf-8 -*- def consumer(): r = '' while True: n = yield r print("[Consumer] n = %d" %n) if not n: return print("[Consumer] consuming %s..."

  • Spring Boot Async异步执行任务过程详解

    异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑. 通常我们使用异步操作都会去创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代码如下: ExecutorService executorService = Executors.newFixedThreadPool(10); executorService.execute(() -> { try { // 业务逻辑 } catch (Exception e) { e.printStackTrace(

  • c#中task与thread区别及其使用的方法示例

    目录 1.什么是thread 2.什么是task 3.创建一个task任务有两种模式: 1.什么是thread 当我们提及多线程的时候会想到thread和threadpool,这都是异步操作,threadpool其实就是thread的集合,具有很多优势,不过在任务多的时候全局队列会存在竞争而消耗资源.thread默认为前台线程,主程序必须等线程跑完才会关闭,而threadpool相反. 总结:threadpool确实比thread性能优,但是两者都没有很好的api区控制,如果线程执行无响应就只能

  • c#中task与thread的区别及使用讲解

    目录 一.什么是thread 二.什么是task 三.创建一个task任务有两种模式 1.使用factory创建会直接执行 2.我们来看看task的生命周期 3.下面演示几个控制task的方法 4.task的回调执行 5.task的取消 6.task的嵌套 6.task死锁的问题 7.对Spinlock的使用 一.什么是thread 当我们提及多线程的时候会想到thread和threadpool,这都是异步操作,threadpool其实就是thread的集合,具有很多优势,不过在任务多的时候全局

  • 详解redux异步操作实践

    一.redux基础 redux 通过 dispatch(action) -> 中间件 -> reducer处理数据 -> 改变store -> 使用subscribe()监听store改变更新视图 的方式管理状态 将所有状态存储在一个store对象里面 reducer为纯函数,而异步操作由于结果的不确定性所以含有副作用,所以需要特殊处理 react-redux 容器组件,负责管理数据和业务逻辑,不负责UI呈现 UI组件,提供UI呈现,无状态即不使用this.state,状态全部由t

随机推荐