.Net使用Cancellation Framework取消并行任务

 更新时间:2022年06月17日 09:41:19   作者:天方  
这篇文章介绍了.Net使用Cancellation Framework取消并行任务的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

在.net 4.0中,引入了一个新的类CancellationToken,这个类基本上集成了我们各种常用的取消方式,在并发任务中非常有用。

同步模式下的取消:

一种比较常见的需要支持取消功能的的是一些比较耗时的分段操作:如视频转换,网络下载等,这种方式下的取消机制如下:

  • 建立一个标记位,表示该操作是否已经取消

  • UI线程在获取到取消事件后,置标记位为true

  • 耗时的操作线程里,没进行一小段操作之后查询该标记位,如果为true则主动退出。

使用方式如下:

    EventHandler externalEvent;
    void Example1()
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        externalEvent +=
         (sender, obj) => { cts.Cancel(); }; //wire up an external requester 
        try
        {
            int val = LongRunningFunc(cts.Token);
        }
        catch (OperationCanceledException)
        {
            //cleanup after cancellation if required... 
        }
    }

    private static int LongRunningFunc(CancellationToken token)
    {
        int total = 0;
        for (int i = 0; i < 1000; i++)
        {
            for (int j = 0; j < 1000; j++)
            {
                total++;
            }
            if (token.IsCancellationRequested)
            { // observe cancellation 
                throw new OperationCanceledException(token); // acknowledge cancellation 
            }
        }
        return total;
    }

异步模式下的取消

另外一种常见的方式是在一些异步操作中,往往不能主动释放,只能等待异步操作回调的时候才能操作结果。此时一般取消方法如下:

  • 任务线程注册异步操作完成的回调函数,开始异步操作。

  • UI线程接受取消指令,置取消标记位,并主动执行回调函数

  • 回调函数中通过取消标记位判断该任务是已经完成还是被取消的,并执行相关析构操作。

使用方式如下:

    void BlockingOperation(CancellationToken token)
    {
        ManualResetEvent mre = new ManualResetEvent(false);
        //register a callback that will set the MRE 
        CancellationTokenRegistration registration =
         token.Register(() => mre.Set());
        using (registration)
        {
            mre.WaitOne();
            if (token.IsCancellationRequested) //did cancellation wake us? 
                throw new OperationCanceledException(token);
        } //dispose the registration, which performs the deregisteration. 
    }

这里我们通过CancellationToken注册了一个回调方法以通知任务等待线程,也可以以我们经常使用的WaitHandle的那样的方式使用。

    void Wait(WaitHandle wh, CancellationToken token)
    {
        WaitHandle.WaitAny(new[] { wh, token.WaitHandle });
        if (token.IsCancellationRequested) //did cancellation wake us? 
            throw new OperationCanceledException(token);
    }

高级应用

由于例子比较简单,这里就只列举一下代码,不多介绍了。

一个CancellationToken对应多个任务

    void Example4()
    {
        CancellationTokenSource cts = new CancellationTokenSource();
        Func1(cts.Token);
        Func2(cts.Token);
        Func3(cts.Token);
        //... 
        cts.Cancel(); // all listeners see the same cancellation request. 
    }

一个任务对应多个CancellationToken

    void LinkingExample(CancellationToken ct1, CancellationToken ct2)
    {
        CancellationTokenSource linkedCTS =
        CancellationTokenSource.CreateLinkedTokenSource(ct1, ct2);
        try
        {
            SlowFunc(linkedCTS.Token);
        }
        catch (OperationCanceledException oce)
        {
            if (ct1.IsCancellationRequested)
            {
                // ... 
            }
            else if (ct2.IsCancellationRequested)
            {
                // ... 
            }
        }
        linkedCTS.Dispose(); // clean up the linking. required. 
    }

最后我们再来一个并发查询时取消的例子:

    private void RunQuery()
    {
        int[] data = { 1, 2, 3 };
        CancellationTokenSource cts = new CancellationTokenSource();
        var query = data.AsParallel()
                     .WithCancellation(cts.Token) // token given to library code 
                     .Select((x) => SlowFunc(x, cts.Token)); // token passed to user code 
    }

    private int SlowFunc(int x, CancellationToken token) 
    { 
        int result 
        while(...) 
        { 
            if (token.IsCancellationRequested) 
            throw new OperationCanceledException(token); 
            ... 
        } 
        return result; 
    }

小结

.net 4.0中的Cancellation Framework还是非常实用的,通过它可以更有效的简化及规范的使用各种取消的操作方式,由于我也只会皮毛,在这里也只是介绍了它的基本用法,在后续的学习和应用中将继续进一步介绍。

到此这篇关于.Net使用Cancellation Framework取消并行任务的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • asp.net实现调用带有输出参数的存储过程实例

    asp.net实现调用带有输出参数的存储过程实例

    这篇文章主要介绍了asp.net实现调用带有输出参数的存储过程,结合实例形式分析了前端基于jQuery的ajax调用及后台存储过程调用的相关技巧,需要的朋友可以参考下
    2016-03-03
  • .NET8实现PDF合并的示例代码

    .NET8实现PDF合并的示例代码

    这篇文章主要为大家详细介绍了如何使用.NET8实现PDF合并的效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • GridView导出Excel实现原理与代码

    GridView导出Excel实现原理与代码

    使用GridView来展示数据库表,几乎没对GridView的格式做什么设定,从配置文件中加载SQL,跑出数据就直接绑定到GridView,接下来介绍导出Excel的功能感兴趣的朋友可以参考下
    2013-01-01
  • asp.net core集成MongoDB的完整步骤

    asp.net core集成MongoDB的完整步骤

    前两天在学习MongoDB相关的知识,做了个小Demo,下面这篇文章主要给大家介绍了关于asp.net core集成MongoDB的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-10-10
  • 详解ASP.NET Core3.0 配置的Options模式

    详解ASP.NET Core3.0 配置的Options模式

    这篇文章主要介绍了详解ASP.NET Core3.0 配置的Options模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • .NET+JS对用户输入内容进行字数提示功能的实例代码

    .NET+JS对用户输入内容进行字数提示功能的实例代码

    .NET+JS对用户输入内容进行字数提示功能的实例代码,需要的朋友可以参考一下
    2013-06-06
  • .Net Core WebApi部署在Linux服务器上的方法

    .Net Core WebApi部署在Linux服务器上的方法

    这篇文章主要介绍了.Net Core WebApi部署在Linux服务器上的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • ASP.NET泛型四之使用Lazy<T>实现延迟加载

    ASP.NET泛型四之使用Lazy<T>实现延迟加载

    这篇文章介绍了ASP.NET泛型使用Lazy<T>实现延迟加载的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-08-08
  • .net中string无重复数字的实现方法

    .net中string无重复数字的实现方法

    今天做项目的时候,用js获得了勾选的checkbox放在了hiddenfile里,然而hiddenfile的值变成了类似:“1,1,1,3,3,2,4,5,5,5”,后台获取的时候,只保留不重复的数字,于是想了一想;直接上代码了。
    2013-04-04
  • Visual Studio 2013+OpenCV2.4.10环境搭建教程

    Visual Studio 2013+OpenCV2.4.10环境搭建教程

    这篇文章主要为大家详细介绍了Visual Studio 2013+OpenCV2.4.10环境搭建教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01

最新评论