C# task应用实例详解

 更新时间:2020年6月25日 10:34  点击:1893

Task的应用

​Task的MSDN的描述如下:

【Task类的表示单个操作不会返回一个值,通常以异步方式执行。

Task对象是一种的中心思想基于任务的异步模式首次引入.NETFramework 4 中。

因为由执行工作Task对象通常以异步方式执行线程池线程上而不是以同步方式在主应用程序线程中,可以使用Status属性,并将IsCanceled, IsCompleted,和IsFaulted属性,以确定任务的状态。

大多数情况下,lambda 表达式用于指定该任务所执行的工作量。

对于返回值的操作,您使用Task类。】

我对于Task的理解是这样的,Task是FrameWork4引进的新功能,他和ConCurrent命名空间一起被引进,用来替代Thread的使用。

根据我的使用,个人觉得,他确实比Thead的功能要丰富一些。

下面我们一起看一个最简单的例子:

using System;
using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;namespace TaskConsole
{  class Program
  {    static void Main(string[] args)
    {      //当前线程标识      Console.WriteLine(Thread.CurrentThread.GetHashCode());
      Task task = new Task(run);
      Console.WriteLine("任务标识:" + task.GetHashCode() + ",状态:" + task.Status);//状态       task.Start();
      Console.WriteLine("任务标识:" + task.GetHashCode() + ",状态:" + task.Status);//状态      //任务完成后执行新任务
      Action ation = new Action(taskStart);
      task.ContinueWith(ation);

      Console.Read();
    }    public static void taskStart(Task task)
    {
      task = new Task(run);
      task.Start();      //如果注释上面两句话,则任务标识为 task.ContinueWith(ation)中task的任务
      Console.WriteLine("任务标识:" + task.GetHashCode() + ",状态:" + task.Status + ",当前线程:" + Thread.CurrentThread.GetHashCode());//状态       
    }    public static void run()
    { 
      Console.WriteLine("this is run");
    }
  }
}

一,task.GetHashCode(),是获取Task实例的唯一标识,每个Task都不一样。

测试发现,Task.GetHashCode()并不等于Thread.CurrentThread.GetHashCode()。

二,task.ContinueWith(),是任务结束后继续执行任务的方法,传一个Action,当任务结束后,触发该Action。

任务刚new出来的时候,task就又状态了,是Created,一但运行了,状态就是WaitingToRun。

运行结果如下:

根据MSDN的说明,Task.State是获取TaskState的枚举值,其枚举值代表的意义如下

|Canceled |该任务已通过对其自身的 CancellationToken 引发 OperationCanceledException 对取消进行了确认,此时该标记处于已发送信号状态;或者在该任务开始执行之前,已向该任务的 CancellationToken 发出了信号。 有关更多信息,请参见任务取消。

| Created |该任务已初始化,但尚未被计划。

| Faulted |由于未处理异常的原因而完成的任务。

| RanToCompletion |已成功完成执行的任务。

| Running |该任务正在运行,但尚未完成。

| WaitingForActivation |该任务正在等待 .NET Framework 基础结构在内部将其激活并进行计划。

| WaitingForChildrenToComplete |该任务已完成执行,正在隐式等待附加的子任务完成。

| WaitingToRun |该任务已被计划执行,但尚未开始执行。

任务嵌套

任务嵌套就是指在一个任务中又创建了一个任务。

而新建的任务就是子任务。在没有特殊声明的情况下,父子任务是一起运行的。

如SimpleNestedTask方法。

父子任务关联需要在创建子任务的时候,增加参数TaskCreationOptions.AttachedToParent。

将父子任务关联起来,此时父任务将等待子任务结束,才会完成。

如果使用Task创建任务,不需要使用TaskCreationOptions.AttachedToParent参数,因为只要父任务使用了子任务的返回结果,父任务自然就会等待子任务完成。

public class Program
 {
 static void Main(string[] args)
 { 
 WaitForSimpleNestedTask();
 Console.WriteLine("=====================================================");
 SimpleNestedTask();
 Thread.SpinWait(600000);//等待SimpleNestedTask结束 再运行
 Console.WriteLine("=====================================================");
 //SimpleNestedTaskAttachedToParent();
 Console.Read();
 }
 static void WaitForSimpleNestedTask()
 {
 var outer = Task.Factory.StartNew(() =>
 {
 Console.WriteLine("Outer1 task executing.");

 var nested = Task.Factory.StartNew(() =>
 {
 Console.WriteLine("Nested1 task starting.");
 Thread.SpinWait(5000000);
 Console.WriteLine("Nested1 task completing.");
 return 42;
 });
 return nested.Result;
 return 1;
 });
 Console.WriteLine("Outer1 has returned {0}.", outer.Result);
 }
 static void SimpleNestedTask()
 {
 var parent = Task.Factory.StartNew(() =>
 {
 Console.WriteLine("Outer2 task executing.");

 var child = Task.Factory.StartNew(() =>
 {
 Console.WriteLine("Nested2 task starting.");
 Thread.SpinWait(500000);
 Console.WriteLine("Nested2 task completing.");
 });
 });
 parent.Wait();
 Console.WriteLine("Outer2 has completed."); 
 }

 static void SimpleNestedTaskAttachedToParent()
 {
 var parent = Task.Factory.StartNew(() =>
 {
 Console.WriteLine("Outer3 task executing.");

 var child = Task.Factory.StartNew(() =>
 {
 Console.WriteLine("Nested3 task starting.");
 Thread.SpinWait(500000);
 Console.WriteLine("Nested3 task completing.");
 }, TaskCreationOptions.AttachedToParent);
 });
 parent.Wait();
 Console.WriteLine("Outer has completed.");
 }

ConCurrent的线程安全的

因为,MSDN将在System.Collections.Concurrent命名空间下的集合,都称为线程安全的集合。

线程安全可以理解为可以被多个线程同时使用的集合,而且同时使用的时候是该集合的值是准确的。

下面举一个使用线程安全集合的例子,使用的是BlockingCollection。

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ParallelConsole
{
 class Program
 {
 
 //定义集合大小为51个,也可以不定义大小
 static BlockingCollection blocking = new BlockingCollection(51);
 
 static void Main(string[] args)
 {
  

  blocking = new BlockingCollection();
  Console.WriteLine("当前blocking为:" + blocking.IsCompleted + "设置了集合大小count一样是0,blocking.Count:" + blocking.Count());
  //当前线程标识
  Console.WriteLine(Thread.CurrentThread.GetHashCode());

  for (int i = 0; i < 3; i++)
  {
  ////如果添加到第3个,就设置添加完成,这时在添加就会抛异常
  //if (i == 3)
  //{
  // blocking.CompleteAdding();
  //}
  
  Action action = new Action(run);
  Task task = new Task(action,i); 
  task.RunSynchronously(); 
  }
  Console.WriteLine("设置添加完成前:" + blocking.IsAddingCompleted);
  //设置添加完成后
  blocking.CompleteAdding();
  Console.WriteLine("设置添加完成后:" + blocking.IsAddingCompleted);
  #region 同步取 取3个
  //for (int i = 0; i < 3; i++)
  //{
  // Action actionTake = new Action(take);
  // actionTake();
  //}
  #endregion
  //并发读取
  
  #region 并发步取 取3个
  //blocking.IsCompleted 只有当集合被添加进内容,然后又都被取光了以后,他才会等于ture,否则都是false
  //当IsCompleted为ture时,就不能再取了否则会抛异常
  
  //同时取,结果是 
  //blocking:0
  //blocking:2
  //blocking:1
  if (!blocking.IsCompleted)//如果集合没取光
  {
  Action actionTake2 = new Action(take);
  Parallel.Invoke(actionTake2, actionTake2, actionTake2);
  }
  #endregion

  Console.WriteLine("当前blocking为:" + blocking.IsCompleted + ",blocking数量为:" + blocking.Count());
  //数据被取光了以后, blocking.Count()为0
  Console.Read();
 }

 public static void take()
 {
  //同步取,blocking.Count()会真实的表现,而异步取,Count是不准确的,因为我取count的时候,可能集合已经又被取出数据了,测试10次肯定会出现不真实的情况
  Console.WriteLine("blocking:" + blocking.Take() + ",blocking数量为:" + blocking.Count());
 }
 public static void run(object i)
 {
  int currentI = int.Parse(i.ToString());
  blocking.TryAdd(currentI); 
 }
 }
}

Parallel

Parallel.Invoke(),并发调用Action,可以传多个Action,也可以传一个Action数据组。

Task

Task(Action,object),这是Task的构造方法,接收Action,object是Action的参数,。

task.RunSynchronously(),他是同步运行任务计划用的,同时他和task.Start()一样,也可以启动线程。

BlockingCollection集合

属性一:IsCompleted,他是表示集合是否有数据,只有当集合被添加进内容,然后又都被取光了以后,他才会等于ture,否则都是false。

属性一:BlockingCollection.IsAddingCompleted,表示是否添加完成。针对blocking.CompleteAdding()的使用,当调用了该方法IsAddingCompleted就为true。

方法一:BlockingCollection.blocking.CompleteAdding(),设置IsAddingCompleted用的。

方法二:BlockingCollection.Add,添加一个实体

方法三:BlockingCollection.TryAdd,添加一个实体,我这里用的是这个方法,区别是,如果添加重复项,他会引发InvalidOperationException这个异常。

方法四:BlockingCollection.Take,从集合中取一个值,注意,是真的取出来,取出来后,BlockingCollection.cout会减一。

运行结果如下:

到此这篇关于C# task应用实例的文章就介绍到这了,更多相关c#task应用内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • C#实现简单的登录界面

    我们在使用C#做项目的时候,基本上都需要制作登录界面,那么今天我们就来一步步看看,如果简单的实现登录界面呢,本文给出2个例子,由简入难,希望大家能够喜欢。...2020-06-25
  • 浅谈C# 字段和属性

    这篇文章主要介绍了C# 字段和属性的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下...2020-11-03
  • C#中截取字符串的的基本方法详解

    这篇文章主要介绍了C#中截取字符串的的基本方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-03
  • C#连接SQL数据库和查询数据功能的操作技巧

    本文给大家分享C#连接SQL数据库和查询数据功能的操作技巧,本文通过图文并茂的形式给大家介绍的非常详细,需要的朋友参考下吧...2021-05-17
  • C#实现简单的Http请求实例

    这篇文章主要介绍了C#实现简单的Http请求的方法,以实例形式较为详细的分析了C#实现Http请求的具体方法,需要的朋友可以参考下...2020-06-25
  • C#中new的几种用法详解

    本文主要介绍了C#中new的几种用法,具有很好的参考价值,下面跟着小编一起来看下吧...2020-06-25
  • 使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序)

    这篇文章主要介绍了使用Visual Studio2019创建C#项目(窗体应用程序、控制台应用程序、Web应用程序),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#开发Windows窗体应用程序的简单操作步骤

    这篇文章主要介绍了C#开发Windows窗体应用程序的简单操作步骤,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-04-12
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • C#和JavaScript实现交互的方法

    最近做一个小项目不可避免的需要前端脚本与后台进行交互。由于是在asp.net中实现,故问题演化成asp.net中jiavascript与后台c#如何进行交互。...2020-06-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • 轻松学习C#的基础入门

    轻松学习C#的基础入门,了解C#最基本的知识点,C#是一种简洁的,类型安全的一种完全面向对象的开发语言,是Microsoft专门基于.NET Framework平台开发的而量身定做的高级程序设计语言,需要的朋友可以参考下...2020-06-25
  • C#变量命名规则小结

    本文主要介绍了C#变量命名规则小结,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-09
  • C#绘制曲线图的方法

    这篇文章主要介绍了C#绘制曲线图的方法,以完整实例形式较为详细的分析了C#进行曲线绘制的具体步骤与相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • C# 中如何取绝对值函数

    本文主要介绍了C# 中取绝对值的函数。具有很好的参考价值。下面跟着小编一起来看下吧...2020-06-25
  • c#自带缓存使用方法 c#移除清理缓存

    这篇文章主要介绍了c#自带缓存使用方法,包括获取数据缓存、设置数据缓存、移除指定数据缓存等方法,需要的朋友可以参考下...2020-06-25
  • c#中(&&,||)与(&,|)的区别详解

    这篇文章主要介绍了c#中(&&,||)与(&,|)的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • 经典实例讲解C#递归算法

    这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下...2020-06-25
  • C#学习笔记- 随机函数Random()的用法详解

    下面小编就为大家带来一篇C#学习笔记- 随机函数Random()的用法详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • C#中list用法实例

    这篇文章主要介绍了C#中list用法,结合实例形式分析了C#中list排序、运算、转换等常见操作技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25