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: 已取消该操作。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章