对于所有需要等待 的操作,例 如 ,因 为文件 、 数据库或网络访 问都需要一定 的时间,此 时就可以启 动一个新线程,同时完成其他任务,即使是处理密集型的任务,线程也是有帮助的。

2 Parallel类

  2.1 用Parallel.For()方法循环

  Parallel.For()方法类似于C#的For循环,多次执行一个任务,它可以并行运行迭代。迭代的顺序没有定义。

1 ParallelLoopResult result = Parallel.For(0, 10, i =>
2             {
3                 Console.WriteLine("{0},task:{1},thread:{2}", i, Task.CurrentId, Thread.CurrentThread.ManagedThreadId);
4                 Thread.Sleep(10);
5             });
6             Console.WriteLine(result.IsCompleted);

  在For()方法中,前两个参数定义了循环的开头和结束。从输出可以看出,顺序是不能保证的。也可以提前中断Parallel.For()方法。

1 ParallelLoopResult result2 = Parallel.For(10, 40, (int i,ParallelLoopState pls) =>
2             {
3                 Console.WriteLine("i: {0},task:{1}", i, Task.CurrentId);
4                 Thread.Sleep(10);
5                 if (i > 15)
6                     pls.Break();
7             });
8             Console.WriteLine(result2.IsCompleted);
9             Console.WriteLine( "lowest break iteration:{0}",result2.LowestBreakIteration);

  2.2 用Parallel.ForEach()方法循环

  paraller.ForEach()方法遍历实现了IEnumerable的集合,其方式类似于Foreach语句,但以异步方式遍历,这里也没有确定的遍历顺序。

1     string[] data = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve" };
2             //  Parallel.ForEach(data, s => { Console.WriteLine(s); });
3             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类 的构造函数在创建任务上提供的灵活性较大.

1    //using TaskFactory
2             Task t1 = new TaskFactory().StartNew(TaskMethod);
3             //using the task factory via task
4             Task t2 = Task.Factory.StartNew(TaskMethod);
5             //using task constructor
6             Task t3 = new Task(TaskMethod);
7             t3.Start();

 

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

1   Task t5 = t4.ContinueWith(DoSecond,TaskContinuationOptions.PreferFairness);

  3.2连续的任务

  通过任务,可 以指定在任务完成后,应 开始运行另一个特定任务.

 1  static void DoOnFirst()
 2         {
 3             Console.WriteLine("doing some task {0}",Task.CurrentId);
 4             Thread.Sleep(3000);
 5         }
 6         static void DoSecond(Task t)
 7         {
 8             Console.WriteLine("task {0} finished",t.Id);
 9             Console.WriteLine("this task id {0}",Task.CurrentId);
10             Console.WriteLine("do some cleanup");
11             Thread.Sleep(3000);
12         }
13 
14  Task t1 = new Task(DoOnFirst);
15             Task t2 = t1.ContinueWith(DoSecond);
16             Task t3 = t2.ContinueWith(DoSecond);
17             Task t4 = t3.ContinueWith(DoSecond);
18             Task t5 = t4.ContinueWith(DoSecond,TaskContinuationOptions.PreferFairness);
19             t1.Start();

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

  3.3任务层次的结构

 1  static void ParentAndChild()
 2         {
 3             var parent = new Task(ParentTask);
 4             parent.Start();
 5             Thread.Sleep(2000);
 6             Console.WriteLine(parent.Status);
 7             Thread.Sleep(4000);
 8             Console.WriteLine(parent.Status);
 9             Console.WriteLine();
10         }
11         private static void ParentTask()
12         {
13             Console.WriteLine("task id {0}",Task.CurrentId);
14             var child = new Task(ChildTask);
15             child.Start();
16             Thread.Sleep(1000);
17             Console.WriteLine("parent started child");
18         }
19 
20         private static void ChildTask()
21         {
22             Console.WriteLine("child");
23             Thread.Sleep(5000);
24             Console.WriteLine("child finished");
25         }

如果父任务在子任务之前结束 ,父 任务的状态就显示为WaitingForChildrenToComplete.只要子任务也结束 时,父任务的状态就变成RanToCompletion。 ·

4 取消架构

  4.1Parallel.For()方法的取消

 1 var cts = new CancellationTokenSource();
 2             cts.Token.Register(() => Console.WriteLine("token canceled"));
 3             new Task(() => { Thread.Sleep(500); cts.Cancel(false); }).Start();
 4             try
 5             {
 6                 ParallelLoopResult result = Parallel.For(0, 100, new ParallelOptions() { CancellationToken = cts.Token, }, x =>
 7                 {
 8                     Console.WriteLine("loop {0} started", x);
 9                     int sun = 0;
10                     for (int i = 0; i < 100; i++)
11                     {
12                         Thread.Sleep(2);
13                         sun += i;
14                     }
15                     Console.WriteLine("loop {0} finished",x);
16                 });
17             }
18             catch (Exception ex)
19             {
20                 Console.WriteLine(ex.Message);
21             }

  4.2任务的取消

   同样的取消模式也可用于任务。

5 线程池

  如果有不同的小任务要完成,就可以事先创建许多线程 ,· 在应完成这些任务时发出请求。 这个线程数最好在需要更多的线程时增加,在 需要释放资源时减少。不需要自己创建这样一个列表。 该列表由 ThreadPool类 托管。 这个类会在需要时增减池中线程的线程数,直 到最大的线程数。 池中的最大线程数是可配置的。如果有更多的作业要处理,线 程池中线程的个数也到了极限,最 新的作业就要排队,且 必须等待线程完成其任务。

 1  static void Main(string[] args)
 2         {
 3             int nWorkerThreads;
 4             int nCompletionPortThreads;
 5             ThreadPool.GetMaxThreads(out nWorkerThreads, out nCompletionPortThreads);
 6             Console.WriteLine("nWorkerThreads:{0},nCompletionPortThreads:{1}", nWorkerThreads, nCompletionPortThreads);
 7 
 8             for (int i = 0; i < 5; i++)
 9             {
10                 ThreadPool.QueueUserWorkItem(JobForAThread);
11             }
12             Thread.Sleep(3000);
13             Console.ReadKey();
14         }
15         static void JobForAThread(object obj)
16         {
17             for (int i = 0; i < 3; i++)
18             {
19                 Console.WriteLine("loop:{0},running inside pooled thread{1}",i,Thread.CurrentThread.ManagedThreadId);
20                 Thread.Sleep(30);
21             }
22         }
View Code

相关文章:

  • 2021-12-15
  • 2021-05-05
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-05
  • 2021-11-08
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-01-31
  • 2022-12-23
  • 2022-12-23
  • 2021-05-08
相关资源
相似解决方案