zoukankan      html  css  js  c++  java
  • C#线程安全使用(四)

    这是时隔多年第四篇,主要是因为身在东软受内网限制,好多文章就只好发到东软内部网站,懒的发到外面,现在一点点把在东软写的文章给转移出来。

    这里主要讲解下CancellationTokenSource,CancellationTokenSource是用于取消线程,具体使用起来有点另类:首先定义实体,然后将其下的属性ToKen传递给线程,当需要取消线程时,调用下Cancel()方法。例子我依然采用了MSDN的例子,但我做了一些修改,这个例子虽然看起来挺复杂,但还是记录了许多内容。

    由于不好理解,我就粗略讲解下:

    Task<double> fTask = factory.ContinueWhenAll(tasks.ToArray(), 上面是创建任务,创建10个线程,并且线程中增加了判断,如果随即数等于0就取消该线程。

     再介绍下factory.ContinueWhenAll,他包含两个参数Task[] tasks,
    Action<Task[]> continuationAction。MSDN的解释是:

    ContinueWhenAll 方法执行 continuationAction 委托,在 tasks 数组的所有任务完成后,无论它们的完成状态。

    MSDN上就这个翻译的还不错,其他的基本可以无视了。。。

    继续看代码,代码中增加了try catch,这是为什么呢,看下ContinueWhenAll英文解释:

    The exception that is thrown when the tasks array is empty

    这里千万不能看中文解释,不然你会凌乱的。看了英文解释就懂了,让任务为空就抛异常。

    那么为什么任务为空呢,因为任务已经被取消了啊,所以为空了。具体代码如下。

    using System;
    using System.Collections.Generic;
    using System.Threading;
    using System.Threading.Tasks;
    public class Example
    {
        public static void Main()
        {
            // Define the cancellation token.
            CancellationTokenSource source = new CancellationTokenSource();
            CancellationToken token = source.Token;
            Random rnd = new Random();
            Object lockObj = new Object();
            List<Task<int[]>> tasks = new List<Task<int[]>>();
            TaskFactory factory = new TaskFactory(token);
            for (int taskCtr = 0; taskCtr <= 10; taskCtr++)
            {
                int iteration = taskCtr + 1;
                tasks.Add(factory.StartNew(() =>
                {
                    int value;
                    int[] values = new int[10];
                    for (int ctr = 1; ctr <= 10; ctr++)
                    {
                        lock (lockObj)
                        {
                            value = rnd.Next(0, 101);
                        }
                        if (value == 0)
                        {
                            source.Cancel();
                            Console.WriteLine("Cancelling at task {0}", iteration);
                            break;
                        }
                       
                        values[ctr - 1] = value;
                    }
                    Console.WriteLine("NO Cancel at task {0}", iteration);
                    return values;
                }, token));
            }
            try
            {
                Task<double> fTask = factory.ContinueWhenAll(tasks.ToArray(),
                                                             (results) =>
                                                             {
                                                                 Console.WriteLine("Calculating overall mean...");
                                                                 long sum = 0;
                                                                 int n = 0;
                                                                 foreach (var t in results)
                                                                 {
                                                                     foreach (var r in t.Result)
                                                                     {
                                                                         sum += r;
                                                                         n++;
                                                                     }
                                                                 }
                                                                 return sum / (double)n;
                                                             }, token);
                Console.WriteLine("The mean is {0}.", fTask.Result);
            }
            catch (AggregateException ae)
            {
                foreach (Exception e in ae.InnerExceptions)
                {
                    if (e is TaskCanceledException)
                        Console.WriteLine("Unable to compute mean: {0}",
                                          ((TaskCanceledException)e).Message);
                    else
                        Console.WriteLine("Exception: " + e.GetType().Name);
                }
            }
            Console.ReadLine();
            
        }
    }

    显示结果图片,每次的结果都不一样的,所以我也是运行了好几次,看这个结果会发现一件事,线程只执行了两个,即当线程2中调用Cancel后,其他线程也被取消了。

    ----------------------------------------------------------------------------------------------------

    注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
    若您觉得这篇文章还不错,请点击下方的推荐】,非常感谢!

     

  • 相关阅读:
    解决Windows 7下IE11无法卸载、无法重新安装,提示安装了更新的IE版本
    [SQL Server] 数据库日志文件自动增长导致连接超时的分析
    DataTable转换为List<T>或者DataRow转换为T
    比较Js的substring、substr和C#的Substring
    .NET(c#)Parameters
    SheetJS保存Excel文件
    SheetJS将table转为Excel
    JS中使用let解决闭包
    Font Awesome图标的粗细
    滚动条样式修改
  • 原文地址:https://www.cnblogs.com/kiba/p/6912585.html
Copyright © 2011-2022 走看看