C#多線程整理

只要有一個前臺線程在運行,應用程序就在運行;如果有多個前臺線程在運行,而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: 已取消該操作。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章