iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >如何理解.NET 4并行编程中Task的取消
  • 927
分享到

如何理解.NET 4并行编程中Task的取消

2023-06-17 14:06:20 927人浏览 安东尼
摘要

如何理解.net 4并行编程中Task的取消,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。因为Task是.NET 4并行编程最为核心的一个类,也我们在是在并行编

如何理解.net 4并行编程中Task的取消,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

因为Task是.NET 4并行编程最为核心的一个类,也我们在是在并行编程常常打交道的类,所以,对Task对全面的了解很有必要。

小编主要讲述如何取消一个task。

在TPL中一个标准化的操作就是”取消Task”。之所以说它是个标准化的操作,其实是把这个操作和之前传统的多线程编程进行比较而言的。

在之前的多线程编程中,我们一般是自己写一些代码来取消线程的运行。但是在.NET 4的TPL中就内置了取消的方法,可能我们觉得TPL没有必要内置这些代码,因为太简单了。但是这个内置的方法不仅仅只是取消了运行的Task,而且还减小了在取消运行的Task时可能产生的一些风险,我们后续文章会详细讲述。

创建一个取消的Task一般要进行下面一些步骤:

a.创建System.Threading.CancellationTokenSource的一个实例:

// create the cancellation token source  ancellationTokenSource tokenSource = new CancellationTokenSource();

b.通过CancellationTokenSource.Token属性获得一个System.Threading.CancellationToken:

CancellationToken token = tokenSource.Token;

c.创建一个新的Task或者Task<T>,并且在构造函数传入Action或者Action<object>的委托作为***个参数,传入CancellationToken作为第二个参数:

Task task = new Task(new Action(printMessage), token);

d.调用Task的Start()方法。

上面的步骤和我们之前介绍的创建一个Task的代码几乎一样,只是在构造函数中多传入了一个参数。

如果想要取消一个Task的运行,只要调用CancellationToken实例的Cancel()方法就可以了。

有点要特别注意的,当我们调用了Cancel()方法之后,.NET Framework不会强制性的去关闭运行的Task。

我们自己必须去检测之前在创建Task时候传入的那个CancellationToken。

我们在创建Task是传入CancellationToken到构造函数,其实这个CancellationToken就是.NET Framework用来避免我们再次运行已经被取消的Task,可以说就是一个标志位。

首先,进入***个议题:

通过轮询的方式检测Task是否被取消

在很多Task内部都包含了循环,用来处理数据。我们可以在循环中通过CancellationToken的IsCancellationRequest属性来检测task是否被取消了。如果这个属性为true,那么我们就得跳出循环,并且释放task所占用的资源(如数据库资源,文件资源等).

我们也可以在task运行体中抛出System.Threading.OperationCanceledException来取消运行的task。

代码如下:

代码

while (true)  {      if (token.IsCancellationRequested)      {            // tidy up and release resources             throw new OperationCanceledException(token);      }       else      {          // do a unit of work         }   }

如果我们没有任何的资源要释放,那么只要简单的调用CancellationToken.ThrowIfCancellationRequested()方法,这个方法会检查是否要取消task,并且抛出异常。代码如下:

while (true)          token.ThrowIfCancellationRequested();          // do a unit of work  }

下面就给出有一个完整的例子:创建一个可以取消的task,并且通过轮询不断的检查是否要取消task

代码如下:

代码       

static void Main(string[] args)          {              // create the cancellation token source              CancellationTokenSource tokenSource = new CancellationTokenSource();               // create the cancellation token              CancellationToken token = tokenSource.Token;              // create the task               Task task = new Task(() =>              {                  for (int i = 0; i < int.MaxValue; i++)                  {                      if (token.IsCancellationRequested)                      {                          Console.WriteLine("Task cancel detected");                          throw new OperationCanceledException(token);                      }                      else                     {                          Console.WriteLine("Int value {0}", i);                      }                  }              }, token);               // wait for input before we start the task              Console.WriteLine("Press enter to start task");              Console.WriteLine("Press enter again to cancel task");              Console.ReadLine();               // start the task              task.Start();               // read a line from the console.              Console.ReadLine();               // cancel the task              Console.WriteLine("Cancelling task");              tokenSource.Cancel();               // wait for input before exiting              Console.WriteLine("Main method complete. Press enter to finish.");              Console.ReadLine();          }

       用委托delegate来检测Task是否被取消

我们可以在注册一个委托到CancellationToken中,这个委托的方法在CancellationToken.Cancel()调用之前被调用。

我们可以用这个委托中的方法来作为一个检测task是否被取消的另外一个可选的方法,因为这个方法是在Cancel()方法被调用之前就调用的,所以这个委托中的方法可以检测task是否被cancel了,也就是说,只要这个委托的方法被调用,那么就说这个CancellationToken.Cancel()方法被调用了,而且在这个委托的方法中我们可以做很多的事情,如通知用户取消操作发生了。

下面的代码给出了一个例子。

代码       

static void Main(string[] args)          {              // create the cancellation token source              CancellationTokenSource tokenSource = new CancellationTokenSource();               // create the cancellation token              CancellationToken token = tokenSource.Token;               // create the task              Task task = new Task(() =>              {                  for (int i = 0; i < int.MaxValue; i++)                  {                      if (token.IsCancellationRequested)                      {                          Console.WriteLine("Task cancel detected");                          throw new OperationCanceledException(token);                      }                      else                     {                          Console.WriteLine("Int value {0}", i);                      }                  }              }, token);               // reGISter a cancellation delegate              token.Register(() =>              {                  Console.WriteLine(">>>>>> Delegate Invoked\n");              });               // wait for input before we start the task              Console.WriteLine("Press enter to start task");              Console.WriteLine("Press enter again to cancel task");              Console.ReadLine();               // start the task              task.Start();              // read a line from the console.              Console.ReadLine();               // cancel the task              Console.WriteLine("Cancelling task");              tokenSource.Cancel();               // wait for input before exiting              Console.WriteLine("Main method complete. Press enter to finish.");              Console.ReadLine();          }

       用Wait Handle还检测Task是否被取消

第三种方法检测task是否被cancel就是调用CancellationToken.WaitHandle属性。对于这个属性的详细使用,在后续的文章中会深入的讲述,在这里主要知道一点就行了:CancellationToken的WaitOne()方法会阻止task的运行,只有CancellationToken的cancel()方法被调用后,这种阻止才会释放。

在下面的例子中,创建了两个task,其中task2调用了WaitOne()方法,所以task2一直不会运行,除非调用了CancellationToken的Cancel()方法,所以WaitOne()方法也算是检测task是否被cancel的一种方法了。

代码       

static void Main(string[] args)         {              // create the cancellation token source             CancellationTokenSource tokenSource = new CancellationTokenSource();              // create the cancellation token             CancellationToken token = tokenSource.Token;              // create the task             Task task1 = new Task(() =>             {                 for (int i = 0; i < int.MaxValue; i++)                 {                     if (token.IsCancellationRequested)                     {                         Console.WriteLine("Task cancel detected");                         throw new OperationCanceledException(token);                     }                     else                    {                         Console.WriteLine("Int value {0}", i);                     }                 }             }, token);              // create a second task that will use the wait handle             Task task2 = new Task(() =>             {                 // wait on the handle                 token.WaitHandle.WaitOne();                 // write out a message                 Console.WriteLine(">>>>> Wait handle released");             });              // wait for input before we start the task             Console.WriteLine("Press enter to start task");             Console.WriteLine("Press enter again to cancel task");             Console.ReadLine();             // start the tasks             task1.Start();             task2.Start();              // read a line from the console.             Console.ReadLine();              // cancel the task             Console.WriteLine("Cancelling task");             tokenSource.Cancel();              // wait for input before exiting             Console.WriteLine("Main method complete. Press enter to finish.");             Console.ReadLine();         }

      取消多个Task

我们可以使用一个CancellationToken来创建多个不同的Tasks,当这个CancellationToken的Cancel()方法调用的时候,使用了这个token的多个task都会被取消。

代码       

static void Main(string[] args)          {              // create the cancellation token source              CancellationTokenSource tokenSource = new CancellationTokenSource();               // create the cancellation token              CancellationToken token = tokenSource.Token;               // create the tasks              Task task1 = new Task(() =>              {                  for (int i = 0; i < int.MaxValue; i++)                  {                      token.ThrowIfCancellationRequested();                      Console.WriteLine("Task 1 - Int value {0}", i);                  }              }, token);               Task task2 = new Task(() =>              {                  for (int i = 0; i < int.MaxValue; i++)                  {                      token.ThrowIfCancellationRequested();                      Console.WriteLine("Task 2 - Int value {0}", i);                  }              }, token);              // wait for input before we start the tasks              Console.WriteLine("Press enter to start tasks");              Console.WriteLine("Press enter again to cancel tasks");              Console.ReadLine();               // start the tasks              task1.Start();              task2.Start();               // read a line from the console.              Console.ReadLine();               // cancel the task              Console.WriteLine("Cancelling tasks");              tokenSource.Cancel();              // wait for input before exiting              Console.WriteLine("Main method complete. Press enter to finish.");              Console.ReadLine();          }

创建组合的取消Task的Token

我们可以用CancellationTokenSource.CreateLinkedTokenSource()方法来创建一个组合的token,这个组合的token有很多的CancellationToken组成。主要组合token中的任意一个token调用了Cancel()方法,那么使用这个组合token的所有task就会被取消。代码如下:

代码       

static void Main(string[] args)         {             // create the cancellation token sources             CancellationTokenSource tokenSource1 = new CancellationTokenSource();             CancellationTokenSource tokenSource2 = new CancellationTokenSource();             CancellationTokenSource tokenSource3 = new CancellationTokenSource();              // create a composite token source using multiple tokens             CancellationTokenSource compositeSource =                  CancellationTokenSource.CreateLinkedTokenSource(             tokenSource1.Token, tokenSource2.Token, tokenSource3.Token);              // create a cancellable task using the composite token             Task task = new Task(() =>             {                 // wait until the token has been cancelled                 compositeSource.Token.WaitHandle.WaitOne();                 // throw a cancellation exception                 throw new OperationCanceledException(compositeSource.Token);             }, compositeSource.Token);              // start the task             task.Start();              // cancel one of the original tokens             tokenSource2.Cancel();              // wait for input before exiting             Console.WriteLine("Main method complete. Press enter to finish.");             Console.ReadLine();         }

      判断一个Task是否已经被取消了

可以使用Task的IsCancelled属性来判断task是否被取消了。代码如下:

代码       

static void Main(string[] args)         {             // create the cancellation token source             CancellationTokenSource tokenSource1 = new CancellationTokenSource();              // create the cancellation token             CancellationToken token1 = tokenSource1.Token;              // create the first task, which we will let run fully             Task task1 = new Task(() =>             {                 for (int i = 0; i < 10; i++)                 {                     token1.ThrowIfCancellationRequested();                     Console.WriteLine("Task 1 - Int value {0}", i);                 }             }, token1);              // create the second cancellation token source             CancellationTokenSource tokenSource2 = new CancellationTokenSource();              // create the cancellation token             CancellationToken token2 = tokenSource2.Token;              // create the second task, which we will cancel             Task task2 = new Task(() =>             {                 for (int i = 0; i < int.MaxValue; i++)                 {                     token2.ThrowIfCancellationRequested();                     Console.WriteLine("Task 2 - Int value {0}", i);                 }             }, token2);              // start all of the tasks             task1.Start();             task2.Start();              // cancel the second token source             tokenSource2.Cancel();             // write out the cancellation detail of each task             Console.WriteLine("Task 1 cancelled? {0}", task1.IsCanceled);             Console.WriteLine("Task 2 cancelled? {0}", task2.IsCanceled);             // wait for input before exiting             Console.WriteLine("Main method complete. Press enter to finish.");             Console.ReadLine();         }

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网精选频道,感谢您对编程网的支持。

--结束END--

本文标题: 如何理解.NET 4并行编程中Task的取消

本文链接: https://www.lsjlt.com/news/290128.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 如何理解.NET 4并行编程中Task的取消
    如何理解.NET 4并行编程中Task的取消,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。因为Task是.NET 4并行编程最为核心的一个类,也我们在是在并行编...
    99+
    2023-06-17
  • 如何理解.NET 4并行编程
    这期内容当中小编将会给大家带来有关如何理解.NET 4并行编程,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1.并行编程和多线程编程的区别。1并行编程。现在随着多核计算机的普及,并行编程技术,也就是多核编...
    99+
    2023-06-17
  • .Net如何使用Cancellation Framework取消并行任务
    本篇内容介绍了“.Net如何使用Cancellation Framework取消并行任务”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所...
    99+
    2023-07-02
  • C++并发编程:如何进行线程终止和取消?
    c++++ 中线程终止和取消机制包括:线程终止:std::thread::join() 阻塞当前线程直到目标线程完成执行;std::thread::detach() 从线程管理中分离目标...
    99+
    2024-05-06
    线程 并发编程 c++
  • 如何在C#项目中使用Task实现并行和多线程编程
    这期内容当中小编将会给大家带来有关如何在C#项目中使用Task实现并行和多线程编程,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。任务和线程的区别:任务是架构在线程之上的,也就是说任务最终还是要抛给线程去执...
    99+
    2023-06-06
  • C++并发编程:如何管理并行线程中的资源分配?
    在多线程程序中,c++++使用互斥锁和原子类型来确保线程对共享资源的正确访问。互斥锁:std::mutex类创建一个互斥锁,允许一次只有一个线程访问共享资源,防止数据竞争。原子类型:st...
    99+
    2024-05-06
    c++ 并发编程 作用域 同步机制 标准库
  • 如何理解Java 并发编程中的ForkJoin框架
    如何理解Java 并发编程中的ForkJoin框架,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1、什么是ForkJoin框架ForkJoin框架是java的JU...
    99+
    2023-06-25
  • 如何理解 mysql5.中的并行复制
    如何理解 mysql5.中的并行复制,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 一 、 前言  &...
    99+
    2024-04-02
  • 如何理解编程中的树
    这篇文章主要讲解了“如何理解编程中的树”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何理解编程中的树”吧!树树是一种非常常用的数据结构,与线性表,堆栈并驾...
    99+
    2024-04-02
  • C++ 函数在并发编程中如何进行状态管理?
    在 c++++ 并发编程中管理函数状态的常见技术包括:线程局部存储 (tls) 允许每个线程维护自己的独立变量副本。原子变量允许在多线程环境中以原子方式读写共享变量。互斥锁通过防止多个线...
    99+
    2024-04-26
    并发编程 状态管理 c++
  • 在Java中如何使用Callable、Future进行并行编程
    这篇文章将为大家详细讲解有关在Java中如何使用Callable、Future进行并行编程,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。使用Callable、Future进行并行编程在Java中进行并行编...
    99+
    2023-05-30
    java callable future
  • 在Go语言中如何处理并发任务取消问题?
    在Go语言中如何处理并发任务取消问题?Go语言作为一门并发编程语言,提供了丰富的并发编程特性,例如goroutine和channel,使得处理并发任务变得非常方便。然而,当涉及到取消并发任务时,我们也需要特殊的机制来保证任务的安全退出。本文...
    99+
    2023-10-22
    Goroutine取消 Context调用 并发任务管理
  • 并发编程之如何理解Future&FutureTask
    本篇内容介绍了“并发编程之如何理解Future&FutureTask”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读...
    99+
    2024-04-02
  • 在Go语言中如何处理并发任务取消问题
    在Go语言中处理并发任务取消问题,可以使用context包来管理和取消任务。首先,使用context包创建一个上下文对象,例如:``...
    99+
    2023-10-09
    Go语言
  • 如何进行C++代码的并发编程?
    如何进行C++代码的并发编程随着计算机技术的发展,多核处理器和并行计算的应用越来越普遍。对于程序开发者来说,如何利用多核处理器的并行计算能力,提高程序的性能成为一个重要的课题。C++作为一个强大的编程语言,在并发编程方面提供了丰富的工具和库...
    99+
    2023-11-03
    C++并发编程
  • 如何理解shell编程中的BASH
    本篇内容介绍了“如何理解shell编程中的BASH”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!认识Bash通过Shell将输入的指令与Ke...
    99+
    2023-06-09
  • 如何在Java中使用Django进行并发编程?
    在Java开发中,Django是一个非常流行的Python web框架,它的并发编程能力也备受推崇。本篇文章将介绍如何在Java中使用Django进行并发编程,同时穿插一些演示代码。 一、Django的并发编程能力 Django的并发编程能...
    99+
    2023-10-16
    git django 并发
  • C++并发编程:如何优化并行算法的性能?
    运用 c++++ 并行编程技术优化并行算法的性能:1. 使用并行算法库简化算法开发;2. 利用 openmp 指令集指定并行执行区域;3. 减少共享内存竞争,使用无锁数据结构、原子操作和...
    99+
    2024-04-30
    c++ 并发编程 同步机制 标准库
  • Python中的并行编程问题及解决方案
    Python中的并行编程问题及解决方案,需要具体代码示例随着多核处理器的普及和计算任务的复杂化,以及数据处理方面的需求增加,利用并行编程可以有效地提高程序的执行效率。Python作为一种高级编程语言,具有简洁、易读、易写的特点,也提供了一些...
    99+
    2023-10-22
    解决方案 并行编程 关键词:Python
  • 如何深入了解.NET编译器中CLR加载过程
    这期内容当中小编将会给大家带来有关如何深入了解.NET编译器中CLR加载过程,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。以下说明CLR加载过程所使用的工具是VS2005+sos.dll,示例程序代码如下...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作