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