Task类(任务)
任务表示应完成的某个单元的工作。这个单元的工作可以在单独的线程中运行,也可以以同步方式启动一个任务,这需要等待主调用线程。使用任务不仅可以获得一个抽象层,还可以对底层线程进行很多控制。
1.启动任务
要启动任务,可以使用TaskFactory类或Task类的构造函数和Start()方法。Task类的构造函数在创建任务上提供的灵活性较大。
1).任务方法
static object taskMethodLock = new object();
static void TaskMethod(object title)
{
lock (taskMethodLock)
{
Console.WriteLine(title);
Console.WriteLine("Task id: {0}, thread: {1}",
Task.CurrentId == null ? "no task" : Task.CurrentId.ToString(),
Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("is pooled thread: {0}", Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine("is background thread: {0}", Thread.CurrentThread.IsBackground);
Console.WriteLine();
}
}
2).使用线程池的任务
static void TasksUsingThreadPool()
{
var tf = new TaskFactory();
Task t1 = tf.StartNew(TaskMethod, "using a task factory"); Task t2 = Task.Factory.StartNew(TaskMethod, "factory via a task"); var t3 = new Task(TaskMethod, "using a task constructor and Start");
t3.Start(); Task t4 = Task.Run(() => TaskMethod("using the Run method"));
}
执行结果:
3).同步任务
任务也可以同步运行,已相同的线程作为主调用线程。
注:主线程是一个调用前台线程,没有任务ID,也不是线程池中的线程。
private static void RunSynchronousTask()
{
TaskMethod("just the main thread");
var t1 = new Task(TaskMethod, "run sync");
t1.RunSynchronously();
}
执行结果:
4).使用单独线程的任务
如果任务的代码应该长时间运行,就应该使用TaskCreationOptions.LogRunning告诉任务调度器创建一个新线程,而不是使用线程池中的线程。
private static void LongRunningTask()
{
var t1 = new Task(TaskMethod, "long running", TaskCreationOptions.LongRunning);
t1.Start();
}
执行结果:
2.Future——任务结果
任务结束时,它可以把一些有用的状态信息写到共享对象中。这个对象必须是线程安全的。另一个选项是使用返回某个结果的任务。这种任务也叫Future,因为它返回一个结果。
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 ResultsFromTasks()
{
var t1 = new Task<Tuple<int, int>>(TaskWithResult, Tuple.Create<int, int>(, ));
t1.Start();
Console.WriteLine(t1.Result);
t1.Wait();
Console.WriteLine("result from task: {0} {1}", t1.Result.Item1, t1.Result.Item2);
}
执行结果:
3.连续任务
通过任务,可以指定在任务完成后,应开始运行另一个特定任务。
注:无论前一个任务是如何结束的,前面的连续任务总是在前一个任务结束时启动。使用TaskContinuationOptions枚举中的值,可以指定,连续任务只有在起始任务成功(或失败)结束时启动。一些可能的值是OnlyOnFaulted、NotOnFaulted、OnlyOnCanceled和OnlyOnRanToCompletion。
static void DoOnFirst()
{
Console.WriteLine("doing some task {0}", Task.CurrentId);
Thread.Sleep();
} static void DoOnSecond(Task t)
{
Console.WriteLine("task {0} finished", t.Id);
Console.WriteLine("this task id {0}", Task.CurrentId);
Console.WriteLine("do some cleanup");
Thread.Sleep();
} static void DoOnError(Task t)
{
Console.WriteLine("task {0} had an error!", t.Id);
Console.WriteLine("my id {0}", Task.CurrentId);
Console.WriteLine("do some cleanup");
}
static void ContinuationTask()
{
Task t1 = new Task(DoOnFirst);
Task t2 = t1.ContinueWith(DoOnSecond);
Task t3 = t1.ContinueWith(DoOnSecond);
Task t4 = t2.ContinueWith(DoOnSecond);
Task t5 = t1.ContinueWith(DoOnError, TaskContinuationOptions.OnlyOnFaulted);
t1.Start(); Thread.Sleep();
}
执行结果:
4.任务层次结构
利用任务连续性,可以在一个任务结束后启动另一个任务。任务也可以构成一个层次结构。一个任务启动一个新任务时,就启动了一个父/子层次结构。
如果父任务在子任务之前结束,父任务的状态就显示为:WaitingForChildrenToComplete。所有的子任务也结束时,父任务的状态就变成RanToCompletion。
static void ParentAndChild()
{
var parent = new Task(ParentTask);
parent.Start();
Thread.Sleep();
Console.WriteLine(parent.Status);
Thread.Sleep();
Console.WriteLine(parent.Status); }
static void ParentTask()
{
Console.WriteLine("task id {0}", Task.CurrentId);
var child = new Task(ChildTask); // , TaskCreationOptions.DetachedFromParent);
child.Start();
Thread.Sleep();
Console.WriteLine("parent started child");
// Thread.Sleep(3000);
}
static void ChildTask()
{
// Console.WriteLine("task id {0}, parent: {1}", Task.Current.Id, Task.Current.Parent.Id);
Console.WriteLine("child");
Thread.Sleep();
Console.WriteLine("child finished");
}
执行结果:
最新文章
- 动手实践 Linux VLAN - 每天5分钟玩转 OpenStack(13)
- UDP server &; client
- 关于通过jq /js 实现验证单选框 复选框是否都有被选中
- WPF中图形表示语法详解(Path之Data属性语法)ZZ
- 再说Play!framework http://hsfgo.iteye.com/blog/806974
- [转]Java程序员们最常犯的10个错误
- POJ 2151 概率DP
- linux 常识笔记 20160621
- jQuery1.8以上,ajaxSend,ajaxStart等一系列事件要绑定在document上才有效果
- 《ruby编程语言》笔记2 对象
- Localdb Attach Problem
- 在win8.1下安装laravel5.1时碰到的坑不少,但总算搞掂,真有点不容易。
- javascript获取页面各种高度
- Lock_sga 和 pre_page_sga 参数详解
- C#后台利用正则表达式查找匹配字符
- UVa 10911 - Forming Quiz Teams
- 【Android】 分享一个完整的项目,适合新手!
- SQL Server数据库基础笔记
- 201521123003《Java程序设计》第12周学习总结
- python爬虫requests模块
热门文章
- BOM的来源是不可能出现的字符,GB2312双字节高位都是1,Unicode理论的根本缺陷导致UTF8的诞生
- [置顶] 【Git入门之一】Git是神马?
- git ignore 的使用
- 尚未在 Web 服务器上注册 ASP.NET 4.0” 的解决办法
- 【转】Android中设置TextView的颜色setTextColor--代码中设置字体颜色
- NET Framework GAC目录构造
- [CODEVS1014]装箱问题
- Asp.net MVC Razor Generator
- JavaScript高级程序设计25.pdf
- <; <; <; 2013年国家集训队作业 >; >; >;