C#之任务,线程和同步
2016-02-06 15:05
375 查看
1 概述
对于所有需要等待 的操作,例 如 ,因 为文件 、 数据库或网络访 问都需要一定 的时间,此 时就可以启 动一个新线程,同时完成其他任务,即使是处理密集型的任务,线程也是有帮助的。2 Parallel类
2.1 用Parallel.For()方法循环
Parallel.For()方法类似于C#的For循环,多次执行一个任务,它可以并行运行迭代。迭代的顺序没有定义。ParallelLoopResult result = Parallel.For(0, 10, i => { Console.WriteLine("{0},task:{1},thread:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(10); }); Console.WriteLine(result.IsCompleted);
在For()方法中,前两个参数定义了循环的开头和结束。从输出可以看出,顺序是不能保证的。也可以提前中断Parallel.For()方法。
ParallelLoopResult result2 = Parallel.For(10, 40, (int i,ParallelLoopState pls) => { Console.WriteLine("i: {0},task:{1}", i, Task.CurrentId); Thread.Sleep(10); if (i > 15) pls.Break(); }); Console.WriteLine(result2.IsCompleted); Console.WriteLine( "lowest break iteration:{0}",result2.LowestBreakIteration);
2.2 用Parallel.ForEach()方法循环
paraller.ForEach()方法遍历实现了IEnumerable的集合,其方式类似于Foreach语句,但以异步方式遍历,这里也没有确定的遍历顺序。string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve" }; // Parallel.ForEach(data, s => { Console.WriteLine(s); }); Parallel.ForEach(data, (s, pls) => { if (s == "one") { Console.WriteLine("break......"); pls.Break(); } Console.WriteLine(s); Thread.Sleep(100); });
2.3 通过Paraller.Invoke()调用多个方法
Parallel.Invoke(Foo ,Bar); static void Foo() { Console.WriteLine("foo"); } static void Bar() { Console.WriteLine("bar"); }
3 任务
.NET 4 包含新的名称空间System.Threading.Task,它它 包含的类抽象出了线程功能,在后台使用ThreadPool。 任务表示应完成的某个单元的工作。 这个单元的工作可以在单独的线程中运行,也可以以同步方式启动一个任务,这需要等待主调线程。3.1启动任务
要启动任务,可 以使用 TaskFactory类 或 Task类 的构造函数和 start()方 法。 Task类 的构造函数在创建任务上提供的灵活性较大.//using TaskFactory Task t1 = new TaskFactory().StartNew(TaskMethod); //using the task factory via task Task t2 = Task.Factory.StartNew(TaskMethod); //using task constructor Task t3 = new Task(TaskMethod); t3.Start();
使用 Task类 的构造函数和 TaskFactory类 的 stamw()方法时,都可以传递TaskCreationOptions枚举中的值。 设置LongRunning选项,可 以通知任务调度器,该 任务需要较长时间执行,这样调度器更可能使用 新线。 如果该任务应关联到父任务上,而父任务取消了,则 该任务也应取消,此 时应设置 AuachToParent选 项。PerferFairness 值表示,调度器应提取出已在等待的第一个任务。 如果任务使用 子任务创建了其他工作,子
任务就优先于其他任务。 它们不会排在线程池队列中的最后。 如果这些任务应 以公平的方式与所有其他任务一起处理,就设置该选项为PreferFairness
Task t5 = t4.ContinueWith(DoSecond,TaskContinuationOptions.PreferFairness);
3.2连续的任务
通过任务,可 以指定在任务完成后,应 开始运行另一个特定任务.static void DoOnFirst() { Console.WriteLine("doing some task {0}",Task.CurrentId); Thread.Sleep(3000); } static void DoSecond(Task t) { Console.WriteLine("task {0} finished",t.Id); Console.WriteLine("this task id {0}",Task.CurrentId); Console.WriteLine("do some cleanup"); Thread.Sleep(3000); } Task t1 = new Task(DoOnFirst); Task t2 = t1.ContinueWith(DoSecond); Task t3 = t2.ContinueWith(DoSecond); Task t4 = t3.ContinueWith(DoSecond); Task t5 = t4.ContinueWith(DoSecond,TaskContinuationOptions.PreferFairness); t1.Start();
无论前一个任务是如何结束的,前 面 的连续任务总是在前一个任务结束时启 动 。 使用TaskContinuationOptions 枚举中的值,可 以指定,连续任务只有在起始任务成功(或失败)结束时启动。
3.3任务层次的结构
static void ParentAndChild() { var parent = new Task(ParentTask); parent.Start(); Thread.Sleep(2000); Console.WriteLine(parent.Status); Thread.Sleep(4000); Console.WriteLine(parent.Status); Console.WriteLine(); } private static void ParentTask() { Console.WriteLine("task id {0}",Task.CurrentId); var child = new Task(ChildTask); child.Start(); Thread.Sleep(1000); Console.WriteLine("parent started child"); } private static void ChildTask() { Console.WriteLine("child"); Thread.Sleep(5000); Console.WriteLine("child finished"); }
如果父任务在子任务之前结束 ,父 任务的状态就显示为WaitingForChildrenToComplete.只要子任务也结束 时,父任务的状态就变成RanToCompletion。 ·
4 取消架构
4.1Parallel.For()方法的取消
var cts = new CancellationTokenSource(); cts.Token.Register(() => Console.WriteLine("token canceled")); new Task(() => { Thread.Sleep(500); cts.Cancel(false); }).Start(); try { ParallelLoopResult result = Parallel.For(0, 100, new ParallelOptions() { CancellationToken = cts.Token, }, x => { Console.WriteLine("loop {0} started", x); int sun = 0; for (int i = 0; i < 100; i++) { Thread.Sleep(2); sun += i; } Console.WriteLine("loop {0} finished",x); }); } catch (Exception ex) { Console.WriteLine(ex.Message); }
4.2任务的取消
同样的取消模式也可用于任务。5 线程池
如果有不同的小任务要完成,就可以事先创建许多线程 ,· 在应完成这些任务时发出请求。 这个线程数最好在需要更多的线程时增加,在 需要释放资源时减少。不需要自己创建这样一个列表。 该列表由 ThreadPool类 托管。 这个类会在需要时增减池中线程的线程数,直 到最大的线程数。 池中的最大线程数是可配置的。如果有更多的作业要处理,线 程池中线程的个数也到了极限,最 新的作业就要排队,且 必须等待线程完成其任务。static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { bool createNew; Mutex m = new Mutex(false, "test", out createNew); if (!createNew) { MessageBox.Show("程序已启动"); Application.Exit(); return; } Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } }
View Code
相关文章推荐
- [小北De编程手记] : Selenium For C# 教程目录
- 在c#中access2003和access2007连接字符串
- c# Winform 下 的ftp传输控制
- c# 根据自定义Attribute排序
- C#文本框中默认是不允许使用全选的
- C# 二叉查找树实现
- C# 基础加强(二) 编译执行过程器
- C# 基础加强(一)可变参数params、索引器
- c#之new关键字
- C#操作字符串方法总结<转>
- C# DataTable 和List之间相互转换的方法
- C# 的List<T>筛选数据填充到另一个List<T>
- c#编程之UDP通信
- C#格式化数值结果表
- crc校验码生成程序(C#)
- C# 串口通信程序
- C#调用VC DLL接口函数参数类型对应介绍
- c#——完美实现短信验证
- C#寒假学习笔记(2)
- C#集合