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方法。

原文地址:https://www.cnblogs.com/YourDirection/p/12500507.html