• C#笔记23:多线程之Task(并行编程)


    C#笔记23:多线程之Task(并行编程)

    1:Task是什么

    2:任务取消

    3:TPL 和传统 .NET 异步编程

        任务并行库 (TPL) 是 .NET Framework 4 版的 System.ThreadingSystem.Threading.Tasks 命名空间中的一组公共类型和 API。TPL 的目的在于简化向应用程序中添加并行性和并发性的过程,从而提高开发人员的工作效率。 TPL 会动态地按比例调节并发程度,以便最有效地使用所有可用的处理器。此外,TPL 还处理工作分区、ThreadPool 上的线程调度、取消支持、状态管理以及其他低级别的细节操作。通过使用 TPL,您可以在将精力集中于程序要完成的工作,同时最大程度地提高代码的性能。

    1:Task是什么

        表示一个异步操作。它是异步操作的首选方式。Task是FRAMEWORK4中的新特性,封装了以前的Thread,并管理Thread。

        任务由 System.Threading.Tasks..::.Task 类表示。返回值的任务由 System.Threading.Tasks..::.Task<(Of <(TResult>)>) 类表示,该类从 Task 继承。任务对象处理基础结构详细信息,并提供可在任务的整个生存期内从调用线程访问的方法和属性。例如,可以随时访问任务的 Status 属性,以确定它是已开始运行、已完成运行、已取消还是引发了异常。状态由 TaskStatus 枚举表示。

    2:任务取消

    namespace CancellationWithOCE
    {
        using System;
        using System.Threading;
        using System.Threading.Tasks;
    
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Press any key to start. Press 'c' to cancel.");
                Console.ReadKey();
    
                var tokenSource = new CancellationTokenSource();
                var token = tokenSource.Token;
    
                // Store references to the tasks so that we can wait on them and
                // observe their status after cancellation.
                Task[] tasks = new Task[10];
    
                // Request cancellation of a single task when the token source is canceled.
                // Pass the token to the user delegate, and also to the task so it can 
                // handle the exception correctly.
                tasks[0] = Task.Factory.StartNew(() => DoSomeWork(1, token), token);
    
                // Request cancellation of a task and its children. Note the token is passed
                // to (1) the user delegate and (2) as the second argument to StartNew, so 
                // that the task instance can correctly handle the OperationCanceledException.
                tasks[1] = Task.Factory.StartNew(() =>
                {
                    // Create some cancelable child tasks.
                    for (int i = 2; i < 10; i++)
                    {
                        // For each child task, pass the same token
                        // to each user delegate and to StartNew.
                        tasks[i] = Task.Factory.StartNew(iteration =>
                                    DoSomeWork((int)iteration, token), i, token);
                    }
                    // Passing the same token again to do work on the parent task. 
                    // All will be signaled by the call to tokenSource.Cancel below.
                    DoSomeWork(2, token);
                }, token);
    
                // Give the tasks a second to start.
                Thread.Sleep(1000);
    
                // Request cancellation from the UI thread.
                if (Console.ReadKey().KeyChar == 'c')
                {
                    tokenSource.Cancel();
                    Console.WriteLine("\nTask cancellation requested.");
    
                    // Optional: Observe the change in the Status property on the task.
                    // It is not necessary to wait on tasks that have canceled. However,
                    // if you do wait, you must enclose the call in a try-catch block to
                    // catch the OperationCanceledExceptions that are thrown. If you do 
                    // not wait, no OCE is thrown if the token that was passed to the 
                    // StartNew method is the same token that requested the cancellation.
    
                    #region Optional_WaitOnTasksToComplete
                    try
                    {
                        Task.WaitAll(tasks);
                    }
                    catch (AggregateException e)
                    {
                        // For demonstration purposes, show the OCE message.
                        foreach (var v in e.InnerExceptions)
                            Console.WriteLine("msg: " + v.Message);
                    }
    
                    // Prove that the tasks are now all in a canceled state.
                    for (int i = 0; i < tasks.Length; i++)
                        Console.WriteLine("task[{0}] status is now {1}", i, tasks[i].Status);
                    #endregion
                }
    
                // Keep the console window open while the
                // task completes its output.
                Console.ReadLine();
            }
    
            static void DoSomeWork(int taskNum, CancellationToken ct)
            {
                // Was cancellation already requested?
                if (ct.IsCancellationRequested)
                {
                    Console.WriteLine("We were cancelled before we got started.");
                    Console.WriteLine("Press Enter to quit.");
                    ct.ThrowIfCancellationRequested();
                }
                int maxIterations = 1000;
    
                // NOTE!!! A benign "OperationCanceledException was unhandled
                // by user code" error might be raised here. Press F5 to continue. Or,
                //  to avoid the error, uncheck the "Enable Just My Code"
                // option under Tools > Options > Debugging.
                for (int i = 0; i < maxIterations; i++)
                {
                    // Do a bit of work. Not too much.
                    var sw = new SpinWait();
                    for (int j = 0; j < 3000; j++) sw.SpinOnce();
                    Console.WriteLine("...{0} ", taskNum);
                    if (ct.IsCancellationRequested)
                    {
                        Console.WriteLine("bye from {0}.", taskNum);
                        Console.WriteLine("\nPress Enter to quit.");
    
                        ct.ThrowIfCancellationRequested();
                    }
                }
            }
        }
    }


    3:TPL 和传统 .NET 异步编程

        见http://msdn.microsoft.com/zh-cn/library/dd997423.aspx

    微信扫一扫,关注最课程(www.zuikc.com),获取更多我的文章,获取软件开发每日一练

    Creative Commons License本文基于Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名http://www.cnblogs.com/luminji(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
  • 相关阅读:
    程序员如何利用空闲时间挣零花钱
    常见的数据交互之跳转页面传值
    一个能让cin和scanf 一样快的方法:
    HDU 4901 DP
    POJ 2823 线段树 Or 单调队列
    POJ 3264 线段树 ST
    POJ 3468 线段树+状压
    POJ 2777 线段树
    QQ 临时会话+图标 HTML代码
    POJ 1463 Strategic game
  • 原文地址:https://www.cnblogs.com/luminji/p/1830837.html
Copyright © 2020-2023  润新知