`
wyf
  • 浏览: 437900 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

取消Thread,取消Task, CancellationTokenSource

    博客分类:
  • C#
阅读更多

1、从 .NET Framework 4 开始,.NET Framework 在协作取消异步操作或长时间运行的同步操作时使用统一的模型。 此模型基于被称为取消标记(CancellationTokenSource)的轻量对象。 调用一个或多个可取消操作的对象(例如通过创建新线程(Thread)或任务(Task))将标记传递给每个操作。

2、用于实现协作取消模型的常规模式是:

3、在以下示例中,请求对象创建 CancellationTokenSource 对象,然后传递其 Token 属性到可取消操作中。 接收请求的操作通过轮询监视标记的 IsCancellationRequested 属性的值。 值变为 true 后,侦听器可以适当方式终止操作。 在此示例中,方法只需退出,很多情况下都只需执行此操作。

using System;
using System.Threading;

public class Example
{
   public static void Main()
   {
      // 创建取消对象实例.
      CancellationTokenSource cts = new CancellationTokenSource();

      // 传递token到取消操作.
      ThreadPool.QueueUserWorkItem(new WaitCallback(DoSomeWork), cts.Token);
      Thread.Sleep(2500);

      // 发送取消操作
      cts.Cancel();
      Console.WriteLine("Cancellation set in token source...");
      Thread.Sleep(2500);
      //取消对象最后要释放。
      cts.Dispose();
   }

   // Thread 2: The listener
   static void DoSomeWork(object obj)
   {
      CancellationToken token = (CancellationToken)obj;

      for (int i = 0; i < 100000; i++) {
         if (token.IsCancellationRequested)
         {
            Console.WriteLine("In iteration {0}, cancellation has been requested...",
                              i + 1);
            // Perform cleanup if necessary.
            //...
            // Terminate the operation.
            break;
         }
         // Simulate some work.
         Thread.SpinWait(500000);
      }
   }
}
// The example displays output like the following:
//       Cancellation set in token source...
//       In iteration 1430, cancellation has been requested...

 Note! 在标记的 IsCancellationRequested 属性设置为 true 后,不能重置为 false 因此,取消后不能重用取消标记。

4、 某些操作可能被阻止,导致其无法及时检查取消标记的值。 对于这些情况,可以注册在接收取消请求时取消阻止此方法的回调方法。

 

Register 方法返回专用于此目的的 CancellationTokenRegistration 对象。此方法可以注册一个取消请求发出后执行的一个操作。 以下示例演示了如何使用 Register 方法取消异步 Web 请求。

using System;
using System.Net;
using System.Threading;

class Example
{
    static void Main()
    {
        CancellationTokenSource cts = new CancellationTokenSource();

        StartWebRequest(cts.Token);

        // cancellation will cause the web 
        // request to be cancelled
        cts.Cancel();
    }

    static void StartWebRequest(CancellationToken token)
    {
        WebClient wc = new WebClient();
        wc.DownloadStringCompleted += (s, e) => Console.WriteLine("Request completed.");

        // Cancellation on the token will 
        // call CancelAsync on the WebClient.
        token.Register(() =>
        {
            wc.CancelAsync();
            Console.WriteLine("Request cancelled!");
        });

        Console.WriteLine("Starting request.");
        wc.DownloadStringAsync(new Uri("http://www.contoso.com"));
    }
}

 5、在更复杂的情况下,用户委托可能需要通知库代码已发生取消。 在这种情况下,终止操作的正确方式是委托调用ThrowIfCancellationRequested 方法,这将引发 OperationCanceledException 库代码可以在用户委托线程上捕获此异常,并检查异常的标记以确定异常是否表示协作取消或一些其他的异常情况。

using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
    static void Main()
    {
        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Factory.StartNew(() =>
        {

            // Were we already canceled?
            ct.ThrowIfCancellationRequested();

            bool moreToDo = true;
            while (moreToDo)
            {
                // Poll on this property if you have to do
                // other cleanup before throwing.
                if (ct.IsCancellationRequested)
                {
                    // Clean up here, then...
                    ct.ThrowIfCancellationRequested();
                }

            }
        }, tokenSource2.Token); // Pass same token to StartNew.

        tokenSource2.Cancel();

        // Just continue on this thread, or Wait/WaitAll with try-catch:
        try
        {
            task.Wait();
        }
        catch (AggregateException e)
        {
            foreach (var v in e.InnerExceptions)
                Console.WriteLine(e.Message + " " + v.Message);
        }
        finally
        {
            tokenSource2.Dispose();
        }

        Console.ReadKey();
    }
}

 

分享到:
评论

相关推荐

    C#多线程并行管理,通过Task实现,可随时暂停,继续以及停止等

    `CancellationTokenSource`是一个控制器,它可以生成一个`CancellationToken`,该令牌可以被传递给`Task`,用于检测是否应该取消任务。当调用`CancellationTokenSource.Cancel()`时,关联的`CancellationToken`会被...

    Task异步执行任务[C#源码]

    4. 进度监控和取消:`Task`支持监控任务状态,以及通过`CancellationToken`实现任务的取消,这在`Thread`中实现起来较为困难。 二、`Task`的创建与执行 1. `Task.Run()`:这是最常用的方法,用于将同步方法包装为...

    C#多线程解决界面卡死问题的完美解决方案

    Thread thread = new Thread(new ThreadStart(BackgroundTask)); thread.Start(); ``` 其中`BackgroundTask`是后台任务的方法。 2. 使用`ThreadPool`:线程池提供了一种高效的方式来复用线程,避免了频繁创建和销毁...

    C#开发之多线程授课实例代码

    创建`CancellationTokenSource`,然后传递其`Token`给`Task`,当需要取消时调用`Cancel`方法。 通过以上这些知识点,你可以构建起C#多线程编程的基础。这个实例代码应该包含了各种多线程技术的演示,包括但不限于...

    winform多线程示例

    同样,为了支持用户取消操作,可以使用`CancellationTokenSource`。这允许我们在后台线程中检查是否已被取消,并相应地停止工作。 6. **错误处理** 在多线程环境中,错误处理至关重要。确保在每个线程中都有适当的...

    .net版本简单线程调用源码_(0610).rar.rar

    通过CancellationTokenSource和CancellationToken可以实现线程的取消: ```csharp CancellationTokenSource cts = new CancellationTokenSource(); cts.Token.ThrowIfCancellationRequested(); // 取消线程 cts....

    C#http的多线程实现

    CancellationTokenSource cts = new CancellationTokenSource(); Task task = Task.Run(async () =&gt; { try { await MyHttpFunctionAsync(cts.Token); } catch (OperationCanceledException) { // 处理取消...

    CleanDiskDemo.rar

    由于这是一个Demo,它可能包含了模拟耗时操作的方法,比如使用`Thread.Sleep`来模拟长时间运行的代码,以便于测试进度条和取消功能的正确性。 通过分析这个Demo,开发者可以学习到如何在C#中实现异步执行、多任务...

    C# 多线程示例代码,全方面展示C#中多线程的各种使用方式

    一种是通过继承`System.Threading.Thread`类并重写`Run()`方法,另一种是使用`System.Threading.Tasks.Task`类或`Task.Run()`方法。`Thread`类更基础,而`Task`更符合异步编程模型,通常用于处理I/O密集型操作。 2....

    多线程实现任务管理器

    在.NET框架中,`System.Threading`命名空间提供了线程相关的类,如`Thread`、`ThreadPool`和`Task`等。`Thread`类是线程的基本表示,可以创建新的线程实例来执行特定的代码块。然而,直接使用`Thread`对象创建大量...

    wpf下多线程的例子

    可以使用 `IProgress&lt;T&gt;` 接口报告进度,并通过 `CancellationTokenSource` 实现取消。 6. **异常处理** 处理多线程中的异常是重要的,因为后台线程上的未捕获异常可能导致程序崩溃。确保在后台任务中使用 `try-...

    C#-正确结束线程-通过给定信号结束线程.rar

    5. **异步编程与Task:** 当使用`Task`进行异步操作时,可以使用`TaskCancelationToken`与`TaskCompletionSource`来控制任务的取消。这提供了一种更高级别的抽象,可以更方便地管理和取消任务,同时避免了线程级别的...

    用《捕鱼达人》去理解C#中的多线程.pdf

    文档中CancellationTokenSource和CancellationToken的使用就表明了如何在任务中使用取消令牌。 5. Task(任务):在.NET 4.0之后引入的Task API是另一种处理异步操作的方法。它提供了比传统线程更高级别的抽象,...

    TaskManager.zip

    `CancellationTokenSource`可以请求取消关联的`CancellationToken`,而`CancellationToken`可以被检查以确定是否已发出取消请求。 7. **async/await 关键字**: 虽然`Task`类是基于回调的异步模式,但C#的`async`...

    C#多线程实例源代码

    推荐使用`CancellationToken`和`CancellationTokenSource`来优雅地取消任务。 总结,C#的多线程特性为我们提供了强大的并发能力,通过实例源代码学习,可以深入理解这些概念,并在实际项目中灵活运用,提升程序性能...

    C#.NET多线程实例6个(包括多线程基本使用,多线程互斥等全部多线程使用实例).rar

    - **线程取消**:`CancellationToken`和`CancellationTokenSource`可以用来优雅地取消正在运行的线程。 5. **多线程中的死锁与活锁** - **死锁**:多个线程互相等待对方释放资源导致无法继续执行的状态。避免死锁...

    C#停止线程的方法

    总结起来,C#中停止线程的最佳实践是使用协作式取消机制,如`CancellationTokenSource`和`CancellationToken`,而不是直接终止线程。这样可以避免潜在的并发问题,确保程序的稳定性和数据一致性。在实际应用中,还...

    winform异步更新UI

    - **CancellationToken/CancellationTokenSource**:用于在异步操作中支持取消,通过`CancellationTokenSource`创建`CancellationToken`,并将其传递给异步方法,当需要取消时调用`Cancel`方法。 5. **最佳实践** ...

    C#精确定时函数,可实现ms级定时,误差不累积

    为了实现这样的需求,C#提供了一系列的API和工具,但默认的`System.Threading.Thread.Sleep()`方法在精度上并不理想,可能会产生较大的误差。本篇将深入探讨如何在C#中创建一个精确定时函数,实现毫秒级定时且误差不...

    Parallel Programming

    通过`CancellationTokenSource`和`CancellationToken`,可以将取消信号传递给任务,使它们能够自行清理资源并停止执行。 6. **Async/Await** 虽然不是专门针对并行编程,但C#的异步编程模型(async/await)与并行...

Global site tag (gtag.js) - Google Analytics