Thread Pool的出現,減輕了撰寫多執行緒應用程式時,所需承擔的執行緒過多而導致效能低落的風險,同時也透過重用執行緒來節省建立執行緒的時間,但是Thread Pool原始的設計仍然是太陽春了點,如前面所展示的,當我們需要等待多個Threads結束才做下一件事時,要嘛就使用Wait Handle在主程式等,要嘛就另外開一個執行緒,於內使用Wait Handle來等待,前者會造成主程式的停滯,後者則會多使用一個執行緒,雖然還是有辦法來調整至完美,但還是需要一道手續。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Threading; namespace ConsoleApplication8 { class Program { static void Main(string[] args) { Stopwatch sw = new Stopwatch(); int foundValue = 29; sw.Start(); for (int i = 0; i < 30; i++) { Thread.Sleep(100); if (i == foundValue) break; } sw.Stop(); long first = sw.ElapsedMilliseconds; Console.WriteLine(sw.ElapsedMilliseconds.ToString()); Random r2 = new Random(4); long sec = 0; for (int v = 0; v < 15; v++) { sw.Reset(); sw.Start(); Random r = new Random(r2.Next(30)); int val = r.Next(30); for (int i = 30; i >= 0; i--) { Thread.Sleep(100); if (val % 30 == foundValue) break; val++; } sw.Stop(); sec += sw.ElapsedMilliseconds; Console.WriteLine(sw.ElapsedMilliseconds.ToString()); } Console.WriteLine("{0} - {1}", (first * 15).ToString(), sec.ToString()); Console.ReadLine(); } } } |
2836 2074 3279 2624 2952 545 2051 2279 1167 2732 2187 1639 874 1312 2625 435 42540 - 28775 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { int i = 0; Random r = new Random(DateTime.Now.Second); Task t = new Task(() => { for(int v = 0; v < 100; v++) i += r.Next(100); }); t.Start(); Console.ReadLine(); t.Wait(); Console.WriteLine(i.ToString()); Console.ReadLine(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication10 { class Program { static void Main(string[] args) { int i = 0; Random r = new Random(DateTime.Now.Second); ManualResetEvent mr = new ManualResetEvent(false); ThreadPool.QueueUserWorkItem((state) => { for(int v = 0; v < 100;v++) i += r.Next(100); mr.Set(); }); Console.ReadLine(); mr.WaitOne(); Console.WriteLine(i.ToString()); Console.ReadLine(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { Task<int> t = new Task<int>(() => { int i = 0; Random r = new Random(DateTime.Now.Second); for(int v = 0; v < 100; v++) i += r.Next(100); return i; }); t.Start(); Console.ReadLine(); Console.WriteLine(t.Result.ToString()); Console.ReadLine(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { Task<int> t = new Task<int>(() => { int i = 0; Random r = new Random(DateTime.Now.Second); for(int v = 0; v < 100; v++) i += r.Next(100); return i; }); t.ContinueWith((Task<int> task) => { Console.WriteLine(task.Result.ToString()); }); t.Start(); Console.ReadLine(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { Task<int> t = new Task<int>(() => { int i = 0; Random r = new Random(DateTime.Now.Second); for(int v = 0; v < 100; v++) i += r.Next(100); return i; }); Task t2 = t.ContinueWith((Task<int> task) => { Console.WriteLine(task.Result.ToString()); }); t2.ContinueWith(task => { Console.WriteLine("done"); }); t.Start(); Console.ReadLine(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { Task<int> t = new Task<int>(() => { Task<int> t1 = new Task<int>(() => { int i = 0; Random r = new Random(DateTime.Now.Second); for (int v = 0; v < 100; v++) i += r.Next(100); return i; },TaskCreationOptions.AttachedToParent); Task<int> t2 = new Task<int>(() => { int i = 0; Random r = new Random(DateTime.Now.Second); for (int v = 0; v < 100; v++) i += r.Next(100); return i; }, TaskCreationOptions.AttachedToParent); Task<int> t3 = new Task<int>(() => { int i = 0; Random r = new Random(DateTime.Now.Second); for (int v = 0; v < 100; v++) i += r.Next(100); return i; }, TaskCreationOptions.AttachedToParent); t1.Start(); t2.Start(); t3.Start(); return t1.Result + t2.Result + t3.Result; }); t.Start(); t.Wait(); Console.WriteLine(t.Result.ToString()); Console.ReadLine(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { int i = 0; Task t = new Task(() => { Task t1 = new Task(() => { Random r = new Random(DateTime.Now.Second); for (int v = 0; v < 100; v++) Interlocked.Add(ref i,r.Next(100)); },TaskCreationOptions.AttachedToParent); Task t2 = new Task(() => { Random r = new Random(DateTime.Now.Second); for (int v = 0; v < 100; v++) Interlocked.Add(ref i, r.Next(100)); }, TaskCreationOptions.AttachedToParent); Task t3 = new Task(() => { Random r = new Random(DateTime.Now.Second); for (int v = 0; v < 100; v++) Interlocked.Add(ref i, r.Next(100)); Thread.Sleep(5000); }, TaskCreationOptions.AttachedToParent); t1.Start(); t2.Start(); t3.Start(); }); t.Start(); t.Wait(); Console.WriteLine(i.ToString()); Console.ReadLine(); } } } |
值 | 說明 |
None | 預設值,此Task會被排入Local Queue中等待執行,採LIFO模式。 |
AttachedToParent | 建立的Task必須是外圍的Task之子Task,一樣是放入Local Queue,採LIFO模式。 |
LongRunning | 建立的Task不受Thread Pool所管理,直接新增一個Thread來執行此Task,無等待、無排程。 |
PreferFairness | 建立的Task直接放入Global Queue中,採FIFO模式。 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication2 { class Program { static void Main(string[] args) { List<string> bags = new List<string>(); for (int i = 0; i < 10; i++) { Task t = new Task(() => { Task t2 = new Task(() => { lock(bags) bags.Add("Inner Thread "+Thread.CurrentThread.ManagedThreadId.ToString()); Thread.Sleep(1000); },TaskCreationOptions.PreferFairness); t2.Start(); lock(bags) bags.Add("Outer Thread "+Thread.CurrentThread.ManagedThreadId.ToString()); Thread.Sleep(1000); }); t.Start(); } Thread.Sleep(15000); foreach (var item in bags) Console.WriteLine(item); Console.ReadLine(); } } } |
Outer Thread 12 Outer Thread 10 Outer Thread 13 Outer Thread 11 Outer Thread 14 Outer Thread 10 Outer Thread 12 Outer Thread 11 Outer Thread 13 Outer Thread 15 Inner Thread 14 Inner Thread 12 Inner Thread 10 Inner Thread 13 Inner Thread 11 Inner Thread 15 Inner Thread 14 Inner Thread 12 Inner Thread 10 Inner Thread 11 |
........ Task t2 = new Task(() => { lock (bags) bags.Add("Inner Thread " + Thread.CurrentThread.ManagedThreadId.ToString()); Thread.Sleep(1000); }); .......... |
Outer Thread 10 Outer Thread 11 Outer Thread 12 Outer Thread 13 Outer Thread 14 Inner Thread 11 Inner Thread 12 Inner Thread 13 Inner Thread 10 Inner Thread 14 Outer Thread 12 Outer Thread 10 Outer Thread 13 Outer Thread 11 Outer Thread 14 Inner Thread 12 Inner Thread 10 Inner Thread 13 Inner Thread 11 Inner Thread 14 |
Inner Thread在沒有PreferFairness的情況下,會被放在Local Queue中,所以會很快的被取出執行,但如果掛上PreferFairness,那麼在Local Queue沒東西的情況下,這些Task才會被執行,所以Inner Thread會被排在Outer Thread全部開始後才開始。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { Task t1 = new Task(() => { for (int v = 0; v < 10; v++) { if (v == 3) throw new DivideByZeroException(); Thread.Sleep(1000); Console.WriteLine(v); } }); t1.Start(); Thread.Sleep(5000); try { t1.Wait(); } catch (AggregateException ex) { foreach (Exception item in ex.InnerExceptions) Console.WriteLine(item.Message); } Console.ReadLine(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { Task t1 = new Task(() => { Task t2 = new Task(() => { for (int v = 0; v < 10; v++) { if (v == 3) throw new DivideByZeroException(); Thread.Sleep(1000); Console.WriteLine(v); } },TaskCreationOptions.AttachedToParent); t2.Start(); }); t1.Start(); Thread.Sleep(5000); try { t1.Wait(); } catch (AggregateException ex) { DumpException(ex); } Console.ReadLine(); } public static void DumpException(AggregateException exception) { foreach (Exception item in exception.InnerExceptions) { if (item is AggregateException) DumpException((AggregateException)item); else Console.WriteLine(item.Message); } } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); var ctoken = cts.Token; Task t1 = new Task(() => { for (int v = 0; v < 10; v++) { ctoken.ThrowIfCancellationRequested(); Thread.Sleep(1000); Console.WriteLine(v); } },ctoken); t1.Start(); Thread.Sleep(2000); cts.Cancel(); try { t1.Wait(); } catch (Exception) { if (t1.IsCanceled) Console.WriteLine("cancel"); } Console.ReadLine(); cts.Dispose(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); var ctoken = cts.Token; Task t1 = new Task(() => { for (int v = 0; v < 10; v++) { if (ctoken.IsCancellationRequested) return; Thread.Sleep(1000); Console.WriteLine(v); } }, ctoken); t1.Start(); Thread.Sleep(2000); cts.Cancel(); t1.Wait(); if (t1.IsCanceled) Console.WriteLine("cancel"); Console.ReadLine(); cts.Dispose(); } } } |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); var ctoken = cts.Token; Task t1 = new Task(() => { for (int v = 0; v < 10; v++) { if (ctoken.IsCancellationRequested) { //clean up. ctoken.ThrowIfCancellationRequested(); } Thread.Sleep(1000); Console.WriteLine(v); } }, ctoken); t1.Start(); Thread.Sleep(2000); cts.Cancel(); try { t1.Wait(); } catch (Exception ex) { if (t1.IsCanceled) Console.WriteLine("cancel"); } Console.ReadLine(); cts.Dispose(); } } } |
Task t1 = new Task(() => { for (int v = 0; v < 10; v++) { if (Task.Current.CancelToken.IsCancellationRequested) { //clean up. Task.Current.CancelToken.ThrowIfCancellationRequested(); } Thread.Sleep(1000); Console.WriteLine(v); } }, ctoken); |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication9 { class Program { static void ThreadFunc(object state) { CancellationToken token = (CancellationToken)state; for (int v = 0; v < 10; v++) { if (token.IsCancellationRequested) { //clean up. token.ThrowIfCancellationRequested(); } Thread.Sleep(1000); Console.WriteLine(v); } } static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); Task t1 = new Task(ThreadFunc, cts.Token,cts.Token); t1.Start(); Thread.Sleep(2000); cts.Cancel(); try { t1.Wait(); } catch (Exception ex) { if (t1.IsCanceled) Console.WriteLine("cancel"); } Console.ReadLine(); cts.Dispose(); } } } |
值 | 說明 |
Created | Task已經建立,但未呼叫Start。 |
WaitingForActivation | Task已排入排程,但尚未執行(一般我們建立的Task不會有此狀態,只有ContinueWith所產生的Task才會有此狀態,容後再述)。 |
WaitingToRun | Task已排入排程,等待執行中。 |
Running | Task執行中。 |
WaitingForChildrenToComplete | Task正等待子Task結束。 |
RanToCompletion | Task已經正常執行完畢。 |
Canceled | Task已被取消。 |
Faulted | Task執行中發生未預期例外。 |
屬性 | 說明 |
IsCompleted | Task已經正常執行完畢。 |
IsFaulted | Task執行中發生未預期例外。 |
IsCanceled | Task已被取消。 |