线程--任务

.net 4包含新名称空间system.Threading.Tasks,它包含的类抽象出了线程功能。在后台使用ThreadPool.任务表示应完成的某个单元的工作。这个单元的工作可以在单独的线程中运行,也可以以同步方式启动一个任务,这需要等待主调线程。

 

使用任务不仅可以获得一个抽象层,还可以对底层线程进行很多控制。在安排需要完成的工作时,任务提供了非常大的灵活性。例如,可以定义连续的工作——在一个任务完成后该执行什么工作。这可以区分任务成功与否。

 

另外,还可以在层次结构中安排任务。例如,父任务可以创建新的子任务。这可以创建一种依赖关系,这样,取消父任务,也会取消其子任务。


1.启动任务

 

要启动任务,可以使用TaskFactory类或Task类的构造函数和startO方法。Task类的构造函数在创建任务上提供的灵活性较大。

在启动任务时,会创建Task类的一个实例,利用Action或Action<object>委托(不带参数或带一个object参数),可以指定应运行的代码。类似于Thread类。

static void Main(string[] args)
        {
            //使用任务工厂
            TaskFactory tf = new TaskFactory();
            Task t1 =tf.StartNew(TaskMethod);
            Task T2 = Task.Factory.StartNew(TaskMethod);
 
            //使用Task构造函数
            Task t3 = new Task(TaskMethod);
            t3.Start();
            Console.ReadKey();
        }
 
        static void TaskMethod()
        {
            Console.WriteLine("启动一个任务.。。");
            Console.WriteLine("Task is:{0}",Task.CurrentId);
        }

第一种方式使用实例化的TaskFactory类,在其中把TaskMedlodO方法传递给StartNew方法,就会立即启动任务。第二种方式使用Task类的构造函数。实例化Task对象时,任务不会立即运行,而是指定Created状态。接着调用Task类的Start方法,来启动任务。使用Task类时,除了调用Start方法,还可以调用RunSynchronously()方法。这样,任务也会启动,但在调用者的当前线程中它正在运行,调用者需要一直等待到该任务结束

 

默认情况下,任务是异步运行的。

 

使用Task类的构造函数和TaskFactory类的StartNew方法时,都可以传递TaskCreationOptions枚举中的值。设置LongRunning选项,可以通知任务调度器,该任务需要较长时间执行,这样调度器更可能使用新线程。如果该任务应关联到父任务上,而父任务取消了,则该任务也应取消,此时应设置AuachToParent选项。PerferTairness的值表示,调度器应提取出已在等待的第一个任务。如果一个任务在另一个任务内部创建,这就不是默认情况。如果任务使用子任务创建了其他工作,子任务就优先于其他任务。它们不会排在线程池队列中的最后。如果这些任务应以公平的方式与所有其他任务一起处理,就设置该选项为PerferTairness。

Task t3 = new Task(TaskMethod,TaskCreationOptions.PreferFairness);
            t3.Start();


2.连续任务

 

通过任务,可以指定在任务完成后,应开始运行另一个特定任务,例如,一个使用前一个任务的结果的新任务,如果前一个任务失败了,这个任务就应执行一些清理工作。

任务处理程序或者不带参数或者带一个对象参数,而连续处理程序有一个Task类型的参数,这里可以访问起始任务的相关信息:

static void Main(string[] args)
        {
            Task t1 = new Task(DoFirst);
            Task t2 = t1.ContinueWith(DoSecond);
            Task t3 = t1.ContinueWith(DoSecond);
            Task t4 = t2.ContinueWith(DoSecond);
            t1.Start();


            Console.ReadKey();
        }

static void DoFirst()
        {
            Console.WriteLine("启动一个任务.。。");
            Console.WriteLine("Task is :{0}", Task.CurrentId);
            Thread.Sleep(3000);
        }

        static void DoSecond(Task t )
        {
            Console.WriteLine("任务{0}完成",t.Id);
            Console.WriteLine("this Task is :{0}", Task.CurrentId);
            Thread.Sleep(3000);
        }

无论前一个任务是如何结束的,前面的连续任务总是在前一个任务结束时启动。使用TaskCreationOptions枚举中的值,可以指定,连续任务只有在起始任务成功(或失败)结束时启动。一些可能的值是OnlyOnFaulted,NotOnFaulted,OnlyOnCanceled,NotOnCanceled和OnlyOnRanToCompletion.

Taskt2 = t1.ContinueWith(DoSecond, TaskCreationOptions.OnlyOnFaulted);


3.任务层次结构

 

利用任务连续性,可以在一个任务结束后启动另一个任务。任务也可以构成一个层次结构。一个任务启动一个新任务时,就启动了一个细子层次结构。

 

如果父任务在子任务之前结束,父任务的状态就显示为WaitingForChildrenToComplete。只要子任务也结束时,父任务的状态就变成RanToCompletion.当然,如果父任务用TaskCreationOptions枚举中的DetachedFormParent创建子任务时,这就无效。

 

取消父任务,也会取消子任务。取消架构后面提到。

 

 

4.任务的结果

 

任务结束时,它可以把一些有用的状态信息写到共享对象中。这个共享对象必须是线程安全的。

另一个选项是使用返回某个结果的任务。使用Task类的泛型版本,就可以定义返回某个结果的任务的返回类型。

 

为了返回某个结果任务调用的方法可以声明为带任意返回类型

static Tuple<int, int> TaskWithResult(object division)
        {
            Tuple<int, int> div = (Tuple<int, int>)division;
            int result = div.Item1 / div.Item2;
            int reminder = div.Item1 % div.Item2;
            Console.WriteLine("task creates a result ...");
            return Tuple.Create<int, int>(result,reminder);
        }

static void Main(string[] args)
        {
            
            var t1 = new Task<Tuple<int, int>>(TaskWithResult,Tuple.Create<int,int>(8,3));
            t1.Start();
            Console.WriteLine(t1.Result);
            t1.Wait();


            Console.ReadKey();
        }


定义一个调用TaskWithResult()方法的任务时,要使用泛型类Task<TResult>。泛型参数定义了返回类型。通过构造函数,把这个方法传递给Func委托,第二个参数定义了输入值。因为这个任务在object参数中需要两个输入值,所以还创建了一个元组。接着启动该任务。Task实例d的Result属性被禁用,并一直等到该任务完成。任务完成后, Result属性包含任务的结果。







  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值