• 一起谈.NET技术,.Net 4.0 Parallel 编程(五)Task (中) 狼人:


      在上篇文章中我们看过了如何创建Task,本篇文章就各种类型Task的使用进行说明。

      Task Continuations

      首先我们来看看延续的Task,所谓的延续的Task就是在第一个Task完成后自动启动下一个Task。我们通过ContinueWith方法来创建延续的Task。我们假设有一个接受xml解析的服务,首先从某个地方接受文件,然后解析入库,最后返回回执是否解析正确:

    [TestMethod]
    public void TaskParallelPrint()
    {
    var ReceiveTask
    = new Task(() => ReceiveXml());
    var ResolveTask
    = ReceiveTask.ContinueWith<bool>((r) => ResolveXml());
    var SendFeedBackTask
    = ResolveTask.ContinueWith<string>((s) => SendFeedBack(s.Result));
    ReceiveTask.Start();
    Console.WriteLine(SendFeedBackTask.Result);
    }

      在每次调用ContinueWith方法时,每次会把上次Task的引用传入进来,以便检测上次Task的状态,比如我们可以使用上次Task的Result属性来获取返回值。上面的代买我们也可以这么写:

    [TestMethod]
    public void TaskParallelPrint()
    {
    var SendFeedBackTask
    = Task.Factory.StartNew(() => ReceiveXml())
    .ContinueWith
    <bool>(s => ResolveXml())
    .ContinueWith
    <string>(r => SendFeedBack(r.Result));
    Console.WriteLine(SendFeedBackTask.Result);
    }

      Detached Nested Tasks

      有些情况下我们需要创建嵌套的Task,嵌套里面又分为分离的和不分离的。其创建的方式很简单,就是在Task的body里面创建一个新的Task。如果新的Task未指定AttachedToParent选项,那么就是分离嵌套的。我们看下面这段代码:

    var outTask = Task.Factory.StartNew(() =>
    {
    Console.WriteLine(
    "Outer task beginning...");
    var childTask
    = Task.Factory.StartNew(() =>
    {
    Thread.SpinWait(
    3000000);
    Console.WriteLine(
    "Detached nested task completed.");
    });
    });
    outTask.Wait();
    Console.WriteLine(
    "Outer task completed.");
    Console.ReadKey();

      我们可以看到运行结果是:

    image  上面的代码中outTask.Wait()表示等待outTask执行完成。

      Child Tasks

      我们将上面的代码加上TaskCreationOptions选项:

    var outTask = Task.Factory.StartNew(() =>
    {
    Console.WriteLine(
    "Outer task beginning...");
    var childTask
    = Task.Factory.StartNew(() =>
    {
    Thread.SpinWait(
    3000000);
    Console.WriteLine(
    "Detached nested task completed.");
    },TaskCreationOptions.AttachedToParent);
    });
    outTask.Wait();
    Console.WriteLine(
    "Outer task completed.");
    Console.ReadKey();

      看到运行结果:

    image  Cancellation Task

      如何取消一个Task呢,我们通过cancellation的tokens来取消一个Task。在很多Task的Body里面包含循环,我们可以在轮询的时候判断IsCancellationRequested属性是否为True,如果是True的话,就可以停止循环以及释放资源,同时抛出OperationCanceledException异常出来。来看一段示例代码:

    var tokenSource = new CancellationTokenSource();
    var token
    = tokenSource.Token;
    var task
    = Task.Factory.StartNew(() =>
    {
    for (var i = 0; i < 10000000; i++)
    {
    if (token.IsCancellationRequested)
    {
    Console.WriteLine(
    "Task cacel started...");
    throw new OperationCanceledException(token);
    }

    }
    },token);
    token.Register(()
    =>
    {
    Console.WriteLine(
    "Canceled");
    });
    Console.WriteLine(
    "Press enter again to cancel task");
    Console.ReadKey();
    tokenSource.Cancel();
    try
    {
    task.Wait();
    }
    catch (AggregateException e)
    {
    foreach (var v in e.InnerExceptions)
    Console.WriteLine(
    "msg: " + v.Message);

    }
    Console.ReadKey();

      总结

      本篇文章中我们看过了创建各种不同的Task以及如何取消Task,下篇文章中会就异常处理以及Task  Laizy进行说明。

  • 相关阅读:
    leetcode刷题笔记 217题 存在重复元素
    leetcode刷题笔记 二百零六题 反转链表
    leetcode刷题笔记 二百零五题 同构字符串
    20201119日报
    np.percentile 和df.quantile 分位数
    建模技巧
    np.where() 条件索引和SQL的if用法一样,或者是给出满足条件的坐标集合
    np.triu_indices_from() 返回方阵的上三角矩阵的索引
    ax.set_title() 和 plt.title(),以及df,plot(title='')
    信用卡模型(三)
  • 原文地址:https://www.cnblogs.com/waw/p/2162731.html
Copyright © 2020-2023  润新知