.net 4.0新增创建线程方法

  .net Framework 4.0添加的一个重要功能是任务并行库(Task Parallel Library TPL),任务并行库(TPL)在两个方面对多线程进行了增强;一:简化了线程的创建和使用。二:自动利用多个处理器。任务并行库(TPL)在System.Threading.Tasks命名空间中定义,因此程序要添加对该命名空间的引用。

  任务并行库(TPL)中的核心类是Task类,对于TPL来说基本执行单元由Task类而非Thread类封装,Task类不同Thread类,Task类是一个表示异步操作的抽象类,在Task类实例和执行线程之间的对应关系不一定是一对一的,因为任务的执行由任务调试程序管理,任务调试程序使用线程池来处理任务,这意味着一些任务可能共享下相同的线程。

一、创建Task类,并开始执行任务。

  示例:  

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Task writeTask = new Task(WriteSomething);
            writeTask.Start();

            Console.WriteLine("writeTask Tag:" + writeTask.Id);

            //注释掉下面二条语句后主线程结束后任务就结束执行。
            writeTask.Wait();
            Console.ReadKey();
        }

        static void WriteSomething()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i);
                Thread.Sleep(500);
            }
        }
    }
}

运行结果如下:

  示例先创建了writeTask实例,然后调用Start()方法开始启动任务,需要注意Task与Thread不同没有Name属性,只有一个标识任务编号的Id属性,而Id值唯一和无序的。示例中有注释写到“注释掉下面二条语句后主程序结束后任务就结束执行”,可以尝试注释掉代码查看结果是在任务刚启动是主线程结束了,任务立刻结束执行。因此Main()方法中调用了Wait()方法等待任务执行结束后再继续执行主线程。

二、创建任务延续和Lambda表达式用任务

  任务并行库(TPL)的一个创新且非常便利的功能就是创建任务延续,延续是在一个任务结束后自动开始下一个任务,延续的方式是通过Task类定义的ContinueWith()方法来实现。自从Lambda表达式引入以来在.net中使用非常广泛,特别是Linq中,在任务延续中也可以使用Lambda表达式用作延续任务。

  示例:

  

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Task task = new Task(WriteSomething);

            Task task2 = task.ContinueWith(WriteSomethingAgain);

            Task lambdaTask = task.ContinueWith((first) =>
            {
                for (int i = 0; i < 5; i++)
                {
                    Console.WriteLine("lambad:" + i);
                    Thread.Sleep(500);
                }
            });           
            task.Start();          

            Console.WriteLine("tag");
            Console.ReadKey();
        }

        static void WriteSomething()
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine(i);
                Thread.Sleep(500);
            }
        }
        static void WriteSomethingAgain(object param)
        {
            for (int i = 0; i < 6; i++)
            {
                Console.WriteLine("write again:"+i);
                Thread.Sleep(500);
            }
        }
    }
}

运行结果:

  

  示例中使用ContinueWith()方法在任务task结束WriteSomething()后,继续开始执行两个任务,分别使用了常规方法和Lambad表达式用执行的任务。

三、从任务返回值

  任务返回值是一个非常有用的功能,一:可以使用任务计算的结果;二、主调线程将阻塞直到结果准备就绪,这意味着不需要特殊的同步来等待结果。要返回结果需要使用Task类的泛型形式创建一个任务,即Task<TResult>。Task<TResult> 实例可以用各种不同的方式创建。最常见的方法是使用任务的 Factory 属性检索可用来创建用于多个用途的任务的 TaskFactory<TResult> 实例

  示例:

  

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //返回值是int类型的任务
            Task<int> taskGetResult = Task<int>.Factory.StartNew(WriteSomethingAgain, 3);
            //返回值是Bool类型的任务
            Task<bool> taskGetBool = Task<bool>.Factory.StartNew(WriteSomethingAgain);
            //通过taskGetResult.Result阻塞主调线程
            Console.WriteLine("TaskGetResult Result:"+taskGetResult.Result);
            //通过taskGetBool.Result阻塞主调线程
            Console.WriteLine("TaskGetResult Result:"+taskGetBool.Result);

            Console.ReadKey();
            
        }       
        static int WriteSomethingAgain(object param)
        {
            for (int i = 0; i < 6; i++)
            {
                Console.WriteLine("write again:"+i);
                Thread.Sleep(500);
            }
            return 10;
        }

        static bool WriteSomethingAgain()
        {
            for (int i = 0; i < 6; i++)
            {
                //Console.WriteLine("write again:" + i);
                Thread.Sleep(00);
            }
            return true;
        }
    }
}

运行结果如下图:

  

四、取消任务

   取消任务基于取消标志(cancellation Token),取消标志从取消标志源(CancellationTokenSource)获取,然后将这个标志传递给任务,任务中必须监视该标志以查看是否有取消请求,如果有取消标志就结束任务,也可以调用ThrowIfCancellationRequested()方法,这样取消代码也知道取消任务已经发生。

  示例:

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace TaskDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            CancellationTokenSource cancelTokenSource = new CancellationTokenSource();

            Task task =Task.Factory.StartNew(MyTaskIfCancelHappenThrownExcetion,cancelTokenSource.Token, cancelTokenSource.Token);
            
            Thread.Sleep(2000);
            try
            {               
                cancelTokenSource.Cancel();
                Thread.Sleep(10);
                task.Wait();
            }
            catch (Exception ex)
            {
                if (task.IsCanceled)
                {
                    Console.WriteLine("Task has been canceled");
                }
            }
            finally
            {
                task.Dispose();
                cancelTokenSource.Dispose();
            }
            Console.WriteLine("Exiting Main...");

            Console.ReadKey();
        }

        static void MyTaskIfCancelHappenThrownExcetion(object cancelToken)
        {
            CancellationToken token = (CancellationToken)cancelToken;

            for (int i = 0; i < 10; i++)
            {
                if (token.IsCancellationRequested)
                {
                    Console.WriteLine("Cancel han been requested");
                    break;
                    //注释break,去掉下面注释,程序会抛出异常,通过异常取消代码接收到取消事件发生。
                    //token.ThrowIfCancellationRequested();
                }
                Console.WriteLine("No cancel requested current value:" + i);

                Thread.Sleep(500);
            }
        }
    }
}

  运行结果如下:

  

  

posted @ 2013-03-20 22:38  mopheify  阅读(2087)  评论(0编辑  收藏  举报