zoukankan      html  css  js  c++  java
  • C# Task 解析(1)

    Task类 定义

    Task 类表示不返回值并且通常以异步方式执行的单个操作。Task 对象是第一次在 .NET Framework 4 中引入的基于任务的异步模式的中心组件之一。 由于 Task 对象执行的工作通常在线程池线程上异步执行,而不是在主应用程序线程上同步执行,因此,您可以使用 "Status" 属性以及 "IsCanceled"、"IsCompleted" 和 "IsFaulted" 属性来确定任务的状态。 

    1.Task自己代码分析

     1         static void Main(string[] args)
     2         {
     3             Console.WriteLine($"Main Start--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
     4             CallMethod();
     5             Console.WriteLine($"Main End--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
     6             Console.ReadKey();
     7         }
     8         
     9         static async void CallMethod()
    10         {
    11             Console.WriteLine($"Call Method Start--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    12             //调用获取密钥方法  带返回参数
    13             Task<string> task1 = GenerateKey_Async();
    14             //执行主线程其他任务
    15             OtherTask();
    16             //通过使用await关键字,等待此任务完成后,才能执行下面代码行。
    17             string myKey = await task1;
    18             //只用当上面一行代码执行完,才会执行解锁方法
    19             Unlock(myKey);
    20 
    21             Console.WriteLine($"Call Method End--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    22         }
    23 
    24         static async Task<string> GenerateKey_Async()
    25         {
    26             string key = "";
    27             await Task.Run(() => {
    28                 Console.WriteLine($"GenerateKey Start--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    29                 Console.WriteLine($"GenerateKey --{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    30                 Thread.Sleep(1000);
    31                 key = "123456";
    32                 Console.WriteLine($"GenerateKey End--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    33             });
    34             return key;
    35         }
    36 
    37         static void Unlock(string key)
    38         {
    39             Console.WriteLine($"Unlock Start--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    40             if(key=="123456")
    41             {
    42                 Console.WriteLine($"Unlock 解锁成功!--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    43             }
    44             Console.WriteLine($"Unlock End--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    45         }
    46 
    47         static async void OtherTask()
    48         {
    49             await Task.Run(() =>
    50             {
    51                 Console.WriteLine($"OtherTask Start--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    52                 Console.WriteLine($"OtherTask --{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    53                 Console.WriteLine($"OtherTask End--{Thread.CurrentThread.ManagedThreadId} {Thread.CurrentThread.IsThreadPoolThread}");
    54             });
    55         }

     可以从上面的结果看出   

    1. 通过await实现了只有当GenerateKey_Async方法执行结束后,才去执行Unlock()方法。

    2. 异步调用task1,不堵塞主线程,让OtherTask方法正常执行。

    3. 发现Call Method Start时 使用了主线程1的资源,但是Call Method End 使用了线程5的资源。这是Task类的一种线程资源分配机制,使得资源分配更为合理。因为当执行Call Method End代码时,主线程的资源早就结束,所以接着使用线程5来完成代码。

    4. 主线程没有使用线程池,但是使用Task创建的线程是使用了线程池,(这个说法好像不是很准确,还要查查资料)

    2. Task.Run() 和 Task.Factory.StartNew()

    public static Task Run(Action action)
    {
        return InternalStartNew(null, action, null, default(CancellationToken), TaskScheduler.Default, TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None);
    }
    
    internal static Task InternalStartNew(Task creatingTask, Delegate action, object state, CancellationToken cancellationToken, TaskScheduler scheduler, TaskCreationOptions options, InternalTaskOptions internalOptions)
    {
        if (scheduler == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
        }
        Task task = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
        task.ScheduleAndStart(needsProtection: false);
        return task;
    }
    public Task StartNew(Action action)
    {
        Task internalCurrent = Task.InternalCurrent;
        return Task.InternalStartNew(internalCurrent, action, null, m_defaultCancellationToken, GetDefaultScheduler(internalCurrent), m_defaultCreationOptions, InternalTaskOptions.None);
    }
    internal static Task InternalStartNew(Task creatingTask, Delegate action, object state, CancellationToken cancellationToken, TaskScheduler scheduler, TaskCreationOptions options, InternalTaskOptions internalOptions)
    {
        if (scheduler == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
        }
        Task task = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
        task.ScheduleAndStart(needsProtection: false);
        return task;
    }

    从上面的源码可以看出,这两个函数都是先创建Task对象,再执行Task对象的Start方法。

  • 相关阅读:
    UGUI组件之Slider组件简单笔记
    UGUI事件之Drag拖拽事件
    C#的数据类型之最常用的几种类型
    UGUI组件之Text文本组件简单笔记
    UGUI组件之Toggle 组件简单笔记
    Print 与Debug.Log的区别
    Unity脚本用VS打开出现 "以下文件中的行尾不一致,要将行尾标准化吗?"
    UGUI组件之Image 组件简单笔记
    UGUI事件之Pointer指针事件
    定制自己的Unity脚本模板
  • 原文地址:https://www.cnblogs.com/YourDirection/p/12500507.html
Copyright © 2011-2022 走看看