只要有一個前臺線程在運行,應用程序就在運行;如果有多個前臺線程在運行,而Main()方法結束了,應用程序進程仍然時激活的,直到所有前臺線程完成爲止。
1. 通過Delegate使用線程
Delegate是通過線程池線程完成異步調用的,線程池線程總是後臺線程。
1.1 通過delegate.BeginInvoke方法啓動線程,通過delegate.EndInvoke(IAsyncResult)等待線程執行結束,並獲取線程函數的返回值。
1.2 通過回調函數等待線程結束,並獲取線程函數執行結果。
/// <summary>
/// 只要有一個前臺線程在運行,應用程序就在運行;
/// 如果有多個前臺線程在運行,而Main()方法結束了,
/// 應用程序進程仍然時激活的,直到所有前臺線程完成爲止。
/// Delegate是通過線程池線程完成異步調用的,線程池線程總是後臺線程。
/// </summary>
public class DelegateWay1
{
public delegate int ThreadFunDelegate(int data, int ms);
/// <summary>
/// 線程函數
/// </summary>
private static int ThreadFun(int data, int ms)
{
Thread.Sleep(ms);
System.Diagnostics.Debug.WriteLine(String.Format("[ThreadFun] data = {0:D}, ms = {1:D}", data, ms));
return ++data;
}
/// <summary>
/// 示例1
/// </summary>
public static void DemoThread1()
{
ThreadFunDelegate dl = ThreadFun;
//觸發異步執行
IAsyncResult ar = dl.BeginInvoke(1, 5000, null, null);
//等待執行完成
int ret = dl.EndInvoke(ar);//也可以使用IAsyncResult.WaitHandle對象來等待
System.Diagnostics.Debug.WriteLine("thread finished, return: " + ret);
}
/// <summary>
/// 委託線程完成時的回調函數(從委託線程調用)
/// </summary>
private static void AsyncCallbackFun(IAsyncResult ar)
{
if(null != ar)
{
//BeginInvoke的第4各參數,可以通過IAsyncResult.AsyncState獲取
ThreadFunDelegate dl = ar.AsyncState as ThreadFunDelegate;
//獲取結果
int ret = dl.EndInvoke(ar);
System.Diagnostics.Debug.WriteLine("callback function: " + ret);
}
}
/// <summary>
/// 示例2
/// </summary>
public static void DemoThread2()
{
ThreadFunDelegate dl = ThreadFun;
//觸發異步執行
IAsyncResult ar = dl.BeginInvoke(1, 5000, AsyncCallbackFun, dl);
System.Diagnostics.Debug.WriteLine("main thread continue ...");
}
}
//運行示例1
private void button1_Click(object sender, EventArgs e)
{
DelegateWay1.DemoThread1();
}
//運行示例2
private void button2_Click(object sender, EventArgs e)
{
DelegateWay1.DemoThread2();
}
2.通過Thread類使用線程
默認情況下Thread類創建的線程總是前臺線程,需要修改IsBackground屬性來指定。
2.1 不帶參數的線程
2.2 帶參數的線程
2.3 使用類的線程
2.4 指定是否爲後臺線程
/// <summary>
/// 只要有一個前臺線程在運行,應用程序就在運行;
/// 如果有多個前臺線程在運行,而Main()方法結束了,
/// 應用程序進程仍然時激活的,直到所有前臺線程完成爲止。
/// Delegate是通過線程池線程完成異步調用的,線程池線程總是後臺線程
/// 默認情況下Thread類創建的線程總是前臺線程,需要修改IsBackground屬性來指定。
/// </summary>
public class MyData
{
public int id;
public string name;
}
public class ThreadWay1
{
/// <summary>
/// 不帶參數的線程函數
/// </summary>
private static void ThreadFun()
{
Thread.Sleep(3000);
System.Diagnostics.Debug.WriteLine("[Thread] thread is finished");
}
/// <summary>
/// 示例1 - 不帶參數的線程
/// </summary>
public static void ThreadDemo1()
{
//通過ThreadStart創建不帶參數的線程
var t1 = new Thread(ThreadFun);
//啓動線程
t1.Start();
}
/// <summary>
/// 帶參數的線程函數
/// </summary>
private static void ThreadFunWithParam(object data)
{
MyData d = (MyData)data;
System.Diagnostics.Debug.WriteLine(String.Format("[Thread] {0:D}, {1}", d.id, d.name));
}
/// <summary>
/// 示例2 - 帶參數的線程
/// </summary>
public static void ThreadDemo2()
{
var data = new MyData() { id = 10, name = "your name" };
var t2 = new Thread(ThreadFunWithParam);
t2.Start(data);
}
/// <summary>
/// 示例3 - 通過類實現傳遞線程參數
/// </summary>
public static void ThreadDemo3()
{
var threadObj = new MyThread("this is a thread object");
var t3 = new Thread(threadObj.ThreadFunc);
t3.Start();
Thread.Sleep(1000);
threadObj.IsStop = true;//停止線程
}
/// <summary>
/// 示例4 - 指定後臺線程
/// </summary>
public static void ThreadDemo4()
{
var t4 = new Thread(ThreadFun) { IsBackground = false };
t4.Start();
}
}
public class MyThread
{
private string data;
private Boolean isStop = false;
public Boolean IsStop { get=>isStop; set=>isStop=value; }
public MyThread(string data)
{
this.data = data;
}
/// <summary>
/// 線程函數
/// </summary>
public void ThreadFunc()
{
while (!IsStop)
{
System.Diagnostics.Debug.WriteLine(String.Format("[Thread] {0}", data));
}
}
}
3. 通過線程池ThreadPool使用線程
使用線程池有一定的條件限制:
- 線程池中的線程都是後臺線程
- 不能給線程池中的線程設置名稱和優先級
- 線程池中的線程都是多線程單元線程(multithreaded
apartment,MTA),但許多COM對象需要單線程單元線程(single-threaded apartment, STA) - 線程池用於時間較短的任務,長時間的如Word拼寫檢查,應該使用Thread類創建一個線程
/// <summary>
/// 線程池有限制:
/// 線程池中的線程都是後臺線程
/// 不能給線程池中的線程設置名稱和優先級
/// 線程池中的線程都是多線程單元線程(multithreaded apartment,MTA),但許多COM對象需要單線程單元線程(single-threaded apartment, STA)
/// 線程池用於時間較短的任務,長時間的如Word拼寫檢查,應該使用Thread類創建一個線程
/// </summary>
public class ThreadPoolWay
{
private static void JobThread(object state)
{
for(int i=0; i<3; ++i)
{
System.Diagnostics.Debug.WriteLine("loop {0}: running in pooled thread {1}.", i, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(50);
}
}
public static void ThreadDemo1()
{
int nWorkerThreads;
int nCompletionPortThreads;
ThreadPool.GetMaxThreads(out nWorkerThreads, out nCompletionPortThreads);
System.Diagnostics.Debug.WriteLine("max worker threads: {0}, I/O completion threads: {1}.", nWorkerThreads, nCompletionPortThreads);
for(int i=0; i<5; ++i)
{
ThreadPool.QueueUserWorkItem(JobThread);
}
}
}
4. 通過任務Task使用線程
System.Threading.Tasks中的TaskFactory、Task類抽象出了線程的功能,在後臺使用ThreadPool.任務提供了非常大的靈活性,比如:
- 可以定義一系列按順序執行的工作(在一個任務完成後繼續執行另外一個任務);
- 可以在層次結構中安排任務,父任務可以創建新的子任務,取消父任務,也會取消其子任務。
4.1 啓動Task
4.2 按順序執行Task
4.3 按層次執行Task
/// <summary>
/// System.Threading.Tasks中的TaskFactory、Task類抽象出了線程的功能,在後臺使用ThreadPool.
/// 任務提供了非常大的靈活性,比如:
/// 可以定義一系列按順序執行的工作(在一個任務完成後繼續執行另外一個任務);
/// 可以在層次結構中安排任務,父任務可以創建新的子任務,取消父任務,也會取消其子任務。
/// </summary>
public class TaskWay
{
private static void TaskFunc()
{
Thread.Sleep(3000);
System.Diagnostics.Debug.WriteLine("Task id: {0}", Task.CurrentId);
}
/// <summary>
/// 示例1 - 啓動任務
/// </summary>
public static void ThreadDemo1()
{
//使用TaskFactory啓動任務
TaskFactory tf = new TaskFactory();
Task t1 = tf.StartNew(TaskFunc);//TaskCreationOptions.LongRunning
//使用Task.Factory啓動任務
Task t2 = Task.Factory.StartNew(TaskFunc);
//使用Task構造函數
Task t3 = new Task(TaskFunc);
t3.Start();
}
private static void DoFirst()
{
Thread.Sleep(3000);
System.Diagnostics.Debug.WriteLine("[DoFirst] Task id: {0}", Task.CurrentId);
}
private static void DoSecond(Task t)
{
Thread.Sleep(3000);
System.Diagnostics.Debug.WriteLine("[DoSecond] Task id: {0}, Task id = {1} finished", Task.CurrentId, t.Id);
}
/// <summary>
/// 示例2 - 連續任務,不管前面的任務是否執行成功
/// </summary>
public static void ThreadDemo2()
{
Task t1 = new Task(DoFirst);
Task t2 = t1.ContinueWith(DoSecond);
Task t3 = t1.ContinueWith(DoSecond);
Task t4 = t2.ContinueWith(DoSecond);
t1.Start();
}
private static void ChildTask()
{
System.Diagnostics.Debug.WriteLine("[ChildTask] start, task id {0}", Task.CurrentId);
Thread.Sleep(8000);
System.Diagnostics.Debug.WriteLine("[ChildTask] finished");
}
private static void ParentTask()
{
System.Diagnostics.Debug.WriteLine("[ParentTask] task id {0}", Task.CurrentId);
var child = new Task(ChildTask);
child.Start();
Thread.Sleep(5000);
System.Diagnostics.Debug.WriteLine("[ParentTask] started child task");
}
private static void ParentAndChild()
{
System.Diagnostics.Debug.WriteLine("[ParentAndChild] start, task id {0}", Task.CurrentId);
var parent = new Task(ParentTask);
parent.Start();
Thread.Sleep(2000);
System.Diagnostics.Debug.WriteLine("[ParentAndChild] parent status = {0}", parent.Status);
Thread.Sleep(4000);
System.Diagnostics.Debug.WriteLine("[ParentAndChild] parent status = {0}", parent.Status);
System.Diagnostics.Debug.WriteLine("[ParentAndChild] finished");
}
/// <summary>
/// 示例3 - 任務的層次
/// </summary>
public static void ThreadDemo3()
{
Task t1 = new Task(ParentAndChild);
t1.Start();
}
}
5. 通過Parallel類使用線程
- Parallel類使用多個任務來完成一個作業
- Parallel.For()和Parallel.ForEach()方法多次調用同一個方法
- Parallel.Invoke()方法允許同時調用不同的方法
- 通過ParallelLoopState類控制和查看循環狀態
5.1 Parallel.For
5.2 Parallel.ForEach
5.3 取消操作
public class ParallelWay
{
/// <summary>
/// 示例1
/// </summary>
public static void ThreadDemo1()
{
//[0, 10)共10個task,也就是10個線程,特別注意迭代的順序無意義不可預知
ParallelLoopResult result = Parallel.For(0, 10, i => {
System.Diagnostics.Debug.WriteLine("{0}, task: {1}, thread: {2}",
i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
});
System.Diagnostics.Debug.WriteLine(result.IsCompleted);
}
/// <summary>
///示例2 - 控制循環
/// ParallelLoopState.Break()可以和其它迭代交互,阻止迭代index大於LowestBreakIteration的迭代啓動,但不影響已經啓動起來的迭代。
/// ParallelLoopState.Stop()則直接退出整個Parallel.For循環。
/// </summary>
public static void ThreadDemo2()
{
ParallelLoopResult result = Parallel.For(0, 100, (int i, ParallelLoopState pls) => {
System.Diagnostics.Debug.WriteLine("beginning iteration {0,2}, task: {1,2}, thread: {2,2}",
i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
if(i == 40)//當改成i >= 40時,可以從運行結果體會"阻止迭代index大於LowestBreakIteration的迭代啓動"
{
System.Diagnostics.Debug.WriteLine("*breaking iteration {0,2}, task: {1,2}, thread: {2,2}",
i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
pls.Break();
}
System.Diagnostics.Debug.WriteLine("completed iteration {0,2}, task: {1,2}, thread: {2,2}",
i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
});
System.Diagnostics.Debug.WriteLine(result.IsCompleted);
System.Diagnostics.Debug.WriteLine("lowest break iteration: {0}", result.LowestBreakIteration);
}
}
示例2 if(i == 40)的執行結果
beginning iteration 25, task: 2, thread: 3
beginning iteration 50, task: 3, thread: 5
beginning iteration 1, task: 5, thread: 6
beginning iteration 0, task: 1, thread: 1
beginning iteration 75, task: 4, thread: 4
beginning iteration 26, task: 6, thread: 7
completed iteration 25, task: 2, thread: 3
completed iteration 50, task: 3, thread: 5
beginning iteration 27, task: 8, thread: 3
completed iteration 0, task: 1, thread: 1
completed iteration 1, task: 5, thread: 6
beginning iteration 2, task: 1, thread: 1
beginning iteration 51, task: 9, thread: 5
completed iteration 75, task: 4, thread: 4
beginning iteration 4, task: 10, thread: 6
beginning iteration 76, task: 11, thread: 4
beginning iteration 53, task: 7, thread: 8
completed iteration 26, task: 6, thread: 7
beginning iteration 29, task: 13, thread: 7
completed iteration 27, task: 8, thread: 3
beginning iteration 28, task: 8, thread: 3
completed iteration 2, task: 1, thread: 1
completed iteration 51, task: 9, thread: 5
beginning iteration 52, task: 9, thread: 5
completed iteration 4, task: 10, thread: 6
completed iteration 76, task: 11, thread: 4
beginning iteration 3, task: 1, thread: 1
beginning iteration 5, task: 10, thread: 6
beginning iteration 77, task: 11, thread: 4
beginning iteration 78, task: 12, thread: 9
completed iteration 53, task: 7, thread: 8
beginning iteration 54, task: 15, thread: 8
completed iteration 29, task: 13, thread: 7
beginning iteration 30, task: 13, thread: 7
completed iteration 28, task: 8, thread: 3
beginning iteration 31, task: 16, thread: 3
completed iteration 52, task: 9, thread: 5
beginning iteration 56, task: 17, thread: 5
completed iteration 3, task: 1, thread: 1
completed iteration 5, task: 10, thread: 6
completed iteration 77, task: 11, thread: 4
beginning iteration 79, task: 19, thread: 4
beginning iteration 6, task: 1, thread: 1
beginning iteration 10, task: 18, thread: 6
completed iteration 78, task: 12, thread: 9
beginning iteration 14, task: 14, thread: 10
beginning iteration 83, task: 21, thread: 9
completed iteration 54, task: 15, thread: 8
beginning iteration 55, task: 15, thread: 8
completed iteration 30, task: 13, thread: 7
beginning iteration 35, task: 22, thread: 7
completed iteration 31, task: 16, thread: 3
beginning iteration 32, task: 16, thread: 3
completed iteration 56, task: 17, thread: 5
beginning iteration 57, task: 17, thread: 5
completed iteration 79, task: 19, thread: 4
completed iteration 6, task: 1, thread: 1
completed iteration 10, task: 18, thread: 6
beginning iteration 7, task: 1, thread: 1
beginning iteration 11, task: 18, thread: 6
beginning iteration 80, task: 19, thread: 4
beginning iteration 39, task: 20, thread: 11
completed iteration 14, task: 14, thread: 10
completed iteration 55, task: 15, thread: 8
completed iteration 35, task: 22, thread: 7
completed iteration 83, task: 21, thread: 9
beginning iteration 84, task: 21, thread: 9
beginning iteration 60, task: 25, thread: 8
completed iteration 32, task: 16, thread: 3
beginning iteration 15, task: 24, thread: 10
beginning iteration 36, task: 22, thread: 7
beginning iteration 33, task: 16, thread: 3
completed iteration 57, task: 17, thread: 5
beginning iteration 58, task: 17, thread: 5
completed iteration 7, task: 1, thread: 1
beginning iteration 8, task: 1, thread: 1
completed iteration 11, task: 18, thread: 6
beginning iteration 12, task: 18, thread: 6
completed iteration 80, task: 19, thread: 4
beginning iteration 81, task: 19, thread: 4
completed iteration 39, task: 20, thread: 11
beginning iteration 64, task: 23, thread: 12
beginning iteration 40, task: 27, thread: 11
completed iteration 84, task: 21, thread: 9
completed iteration 60, task: 25, thread: 8
beginning iteration 61, task: 25, thread: 8
completed iteration 36, task: 22, thread: 7
beginning iteration 37, task: 22, thread: 7
beginning iteration 85, task: 28, thread: 9
completed iteration 15, task: 24, thread: 10
completed iteration 33, task: 16, thread: 3
beginning iteration 34, task: 16, thread: 3
beginning iteration 16, task: 24, thread: 10
completed iteration 58, task: 17, thread: 5
beginning iteration 59, task: 17, thread: 5
completed iteration 8, task: 1, thread: 1
beginning iteration 9, task: 1, thread: 1
completed iteration 12, task: 18, thread: 6
beginning iteration 13, task: 18, thread: 6
completed iteration 81, task: 19, thread: 4
beginning iteration 82, task: 19, thread: 4
beginning iteration 89, task: 26, thread: 13
completed iteration 64, task: 23, thread: 12
beginning iteration 65, task: 30, thread: 12
*breaking iteration 40, task: 27, thread: 11 //下面將不會出現index>40的迭代(61,85,59,82,89,65都是之前啓動的,不受影響,繼續執行)
completed iteration 40, task: 27, thread: 11
completed iteration 61, task: 25, thread: 8
completed iteration 85, task: 28, thread: 9
completed iteration 34, task: 16, thread: 3
completed iteration 37, task: 22, thread: 7
completed iteration 16, task: 24, thread: 10
beginning iteration 17, task: 35, thread: 10
beginning iteration 38, task: 22, thread: 7
completed iteration 59, task: 17, thread: 5
completed iteration 9, task: 1, thread: 1
beginning iteration 21, task: 1, thread: 1
completed iteration 13, task: 18, thread: 6
completed iteration 82, task: 19, thread: 4
completed iteration 89, task: 26, thread: 13
completed iteration 65, task: 30, thread: 12
completed iteration 17, task: 35, thread: 10
completed iteration 38, task: 22, thread: 7
beginning iteration 18, task: 35, thread: 10
completed iteration 21, task: 1, thread: 1
beginning iteration 22, task: 1, thread: 1
completed iteration 18, task: 35, thread: 10
beginning iteration 19, task: 35, thread: 10
completed iteration 22, task: 1, thread: 1
beginning iteration 23, task: 1, thread: 1
completed iteration 19, task: 35, thread: 10
beginning iteration 20, task: 35, thread: 10
completed iteration 23, task: 1, thread: 1
beginning iteration 24, task: 1, thread: 1
completed iteration 20, task: 35, thread: 10
completed iteration 24, task: 1, thread: 1
False
lowest break iteration: 40
示例2 if(i >=40)的執行結果
beginning iteration 0, task: 1, thread: 1
beginning iteration 25, task: 2, thread: 3
beginning iteration 50, task: 3, thread: 5
beginning iteration 75, task: 4, thread: 4
beginning iteration 1, task: 5, thread: 6
beginning iteration 26, task: 6, thread: 7
completed iteration 0, task: 1, thread: 1
beginning iteration 2, task: 1, thread: 1
completed iteration 25, task: 2, thread: 3
*breaking iteration 50, task: 3, thread: 5 //下面將不會有index>50的迭代運行(注意已經啓動的不受影響)
completed iteration 50, task: 3, thread: 5
*breaking iteration 75, task: 4, thread: 4 //下面將不會有index>50(因爲75>50,用最小的)的迭代運行
completed iteration 75, task: 4, thread: 4
beginning iteration 27, task: 8, thread: 3
completed iteration 1, task: 5, thread: 6
beginning iteration 4, task: 11, thread: 4
completed iteration 26, task: 6, thread: 7
beginning iteration 29, task: 12, thread: 5
completed iteration 2, task: 1, thread: 1
beginning iteration 3, task: 1, thread: 1
completed iteration 27, task: 8, thread: 3
beginning iteration 28, task: 8, thread: 3
completed iteration 4, task: 11, thread: 4
beginning iteration 5, task: 11, thread: 4
completed iteration 29, task: 12, thread: 5
beginning iteration 30, task: 12, thread: 5
completed iteration 3, task: 1, thread: 1
beginning iteration 6, task: 1, thread: 1
completed iteration 28, task: 8, thread: 3
beginning iteration 31, task: 13, thread: 3
completed iteration 5, task: 11, thread: 4
beginning iteration 10, task: 14, thread: 4
completed iteration 30, task: 12, thread: 5
beginning iteration 35, task: 15, thread: 6
completed iteration 6, task: 1, thread: 1
beginning iteration 7, task: 1, thread: 1
completed iteration 31, task: 13, thread: 3
beginning iteration 32, task: 13, thread: 3
completed iteration 10, task: 14, thread: 4
beginning iteration 11, task: 14, thread: 4
completed iteration 35, task: 15, thread: 6
beginning iteration 36, task: 15, thread: 6
completed iteration 7, task: 1, thread: 1
beginning iteration 8, task: 1, thread: 1
completed iteration 32, task: 13, thread: 3
beginning iteration 33, task: 13, thread: 3
completed iteration 11, task: 14, thread: 4
beginning iteration 12, task: 14, thread: 4
completed iteration 36, task: 15, thread: 6
beginning iteration 37, task: 15, thread: 6
completed iteration 8, task: 1, thread: 1
beginning iteration 9, task: 1, thread: 1
completed iteration 33, task: 13, thread: 3
beginning iteration 34, task: 13, thread: 3
completed iteration 12, task: 14, thread: 4
beginning iteration 13, task: 14, thread: 4
completed iteration 37, task: 15, thread: 6
beginning iteration 38, task: 15, thread: 6
completed iteration 9, task: 1, thread: 1
beginning iteration 14, task: 1, thread: 1
completed iteration 34, task: 13, thread: 3
beginning iteration 39, task: 16, thread: 5
completed iteration 13, task: 14, thread: 4
beginning iteration 22, task: 17, thread: 3
completed iteration 38, task: 15, thread: 6
beginning iteration 47, task: 18, thread: 4
completed iteration 14, task: 1, thread: 1
beginning iteration 15, task: 1, thread: 1
completed iteration 39, task: 16, thread: 5
beginning iteration 40, task: 16, thread: 5
completed iteration 22, task: 17, thread: 3
beginning iteration 23, task: 17, thread: 3
*breaking iteration 47, task: 18, thread: 4 //下面將不會有index>47(因爲47<50,用最小的)的迭代運行
completed iteration 47, task: 18, thread: 4
completed iteration 15, task: 1, thread: 1
beginning iteration 16, task: 1, thread: 1
*breaking iteration 40, task: 16, thread: 5 //下面將不會有index>40(因爲40<47,用最小的)的迭代運行
completed iteration 40, task: 16, thread: 5
completed iteration 23, task: 17, thread: 3
beginning iteration 24, task: 17, thread: 3
completed iteration 16, task: 1, thread: 1
beginning iteration 17, task: 1, thread: 1
completed iteration 24, task: 17, thread: 3
completed iteration 17, task: 1, thread: 1
beginning iteration 18, task: 1, thread: 1
completed iteration 18, task: 1, thread: 1
beginning iteration 19, task: 1, thread: 1
completed iteration 19, task: 1, thread: 1
beginning iteration 20, task: 1, thread: 1
completed iteration 20, task: 1, thread: 1
beginning iteration 21, task: 1, thread: 1
completed iteration 21, task: 1, thread: 1
False
lowest break iteration: 40
示例3
/// <summary>
/// 特別注意一個線程可能被多個迭代使用
/// </summary>
public static void ThreadDemo3()
{
Parallel.For<string>(0, 6, () => {
//初始化線程,注意線程數可能少於迭代數
var val1 = String.Format("init ({0} {1})", Thread.CurrentThread.ManagedThreadId, Task.CurrentId);
System.Diagnostics.Debug.WriteLine(val1);
return val1;
},
(i, pls, str) => {//線程數少於迭代數時,表面多個迭代使用了同一個線程
var val2 = String.Format("body i={0} ({1} {2}), str=[{3}]",
i, Thread.CurrentThread.ManagedThreadId, Task.CurrentId, str);
System.Diagnostics.Debug.WriteLine(val2);
return val2;
},
(str1) => {//線程結束時掃尾,注意線程數少於迭代數的情況
var val3 = String.Format("fina ({0} {1}), str1=[{2}]", Thread.CurrentThread.ManagedThreadId, Task.CurrentId, str1);
System.Diagnostics.Debug.WriteLine(val3);
});
}
執行結果如下
init (3 2)
init (1 1)
init (4 3)
body i=2 (4 3), str=[init (4 3)]
body i=0 (1 1), str=[init (1 1)]
body i=5 (4 3), str=[body i=2 (4 3), str=[init (4 3)]]
body i=1 (3 2), str=[init (3 2)]
init (6 5)
init (5 4)
body i=4 (6 5), str=[init (6 5)]
fina (6 5), str1=[body i=4 (6 5), str=[init (6 5)]]
fina (4 3), str1=[body i=5 (4 3), str=[body i=2 (4 3), str=[init (4 3)]]]
fina (3 2), str1=[body i=1 (3 2), str=[init (3 2)]]
body i=3 (5 4), str=[init (5 4)]
fina (5 4), str1=[body i=3 (5 4), str=[init (5 4)]]
fina (1 1), str1=[body i=0 (1 1), str=[init (1 1)]]
//把上面結果整理一下,便於看清:
init (3 2)
body i=1 (3 2), str=[init (3 2)]
fina (3 2), str1=[body i=1 (3 2), str=[init (3 2)]]
init (1 1)
body i=0 (1 1), str=[init (1 1)]
fina (1 1), str1=[body i=0 (1 1), str=[init (1 1)]]
init (4 3) //迭代i=2, i=5公用線程
body i=2 (4 3), str=[init (4 3)]
body i=5 (4 3), str=[body i=2 (4 3), str=[init (4 3)]]
fina (4 3), str1=[body i=5 (4 3), str=[body i=2 (4 3), str=[init (4 3)]]]
init (6 5)
body i=4 (6 5), str=[init (6 5)]
fina (6 5), str1=[body i=4 (6 5), str=[init (6 5)]]
init (5 4)
body i=3 (5 4), str=[init (5 4)]
fina (5 4), str1=[body i=3 (5 4), str=[init (5 4)]]
示例4
/// <summary>
/// Parallel.ForEach實現了遍歷IEnumerable的集合
/// </summary>
public static void ThreadDemo4()
{
string[] data = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
ParallelLoopResult result = Parallel.ForEach<string>(data, stringItem => {
System.Diagnostics.Debug.WriteLine("thread={0}, task={1}, data={2}", Thread.CurrentThread.ManagedThreadId, Task.CurrentId, stringItem);
});
}
示例5 - 消息線程
public static void ThreadDemo5()
{
var cts = new CancellationTokenSource();
cts.Token.Register(() => {//取消操作時調用的委託
System.Diagnostics.Debug.WriteLine("callback: token canceled");
});
//1s後取消
new Task(()=> {
Thread.Sleep(1000);
cts.Cancel(false);
}).Start();
try
{
ParallelLoopResult ret = Parallel.For(0, 100,
new ParallelOptions() { CancellationToken = cts.Token },
x => {
System.Diagnostics.Debug.WriteLine("iteration = {0,3} started", x);
int sum = 0;
for(int i=0; i<100; ++i)
{
Thread.Sleep(10);
sum += i;
}
System.Diagnostics.Debug.WriteLine("iteration = {0,3} finished", x);
});
}//一旦取消操作,For()方法就會拋出OperationCanceledException
catch (OperationCanceledException ex)
{
System.Diagnostics.Debug.WriteLine("canceled exception: " + ex.Message);
}
}
執行結果如下:
iteration = 50 started
iteration = 0 started
iteration = 75 started
iteration = 25 started
iteration = 1 started
callback: token canceled
iteration = 0 finished
iteration = 50 finished
iteration = 25 finished
iteration = 75 finished
iteration = 1 finished
Exception thrown: 'System.OperationCanceledException' in mscorlib.dll
canceled exception: 已取消該操作。