本章简言 |
上一章中笔者对C#一些独有的语法点进行讲解,相信也能够看C#的一些神奇之处。那么本章主要是放在多线程这方面的知识。不论是C#仍是JAVA在开发过程或多或少都会用到关于多线程的编程。固然笔者不可能把多线程的知识点讲的很全面。笔者这里只是讲一些笔者经常使用到的。若是有兴趣的朋友,笔者但愿主动性去查找一下资料。编程
Thread类 |
对于Thread类相信JAVA的朋友一点也不陌生。在一点上C#到是跟JAVA很相似。只是在使用上有必定差异。首先要明白C#的多线程功能通常都是在命名空System.Threading下面。至于什么是线程,进程又是什么这样子的问题。笔者就很少说了。相信你们都明白。笔者仍是喜欢直接一点。让咱们看一下代码进行学习吧。多线程
C#:函数
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Thread myThread1 = new Thread(() => 6 { 7 Console.WriteLine("这是一个lambda表达式 建立线程"); 8 }); 9 10 Thread myThread2 = new Thread(ThreadStartImp); 11 12 Thread myThread3 = new Thread((object obj) => 13 { 14 Console.WriteLine("这是一个lambda表达式建立有参数的线程 参数:" + obj.ToString()); 15 }); 16 17 myThread1.Start(); 18 myThread2.Start(); 19 myThread3.Start("aomi"); 20 21 } 22 23 public static void ThreadStartImp() 24 { 25 Console.WriteLine("这是一个用方法建立线程"); 26 } 27 28 29 }
笔者在上面建立三个线程代码。myThread1和myThread2是同一种线程。便是没有参数的线程。myThread3是有参数的线程。不论是不是有参数。使用方式基本是同样子的。有参数的话,就是调用Start方法的时候给他传入一个参数便可。咱们能够看到使用上跟JAVA有一个很大的差异。JAVA的Thread类构造函数的参数传入Runnable接口。惋惜C#不是。以下代码。工具
C#:学习
public Thread(ParameterizedThreadStart start); public Thread(ThreadStart start); public Thread(ParameterizedThreadStart start, int maxStackSize); public Thread(ThreadStart start, int maxStackSize);
这段代码是源码里面的。选中Thread类按F12就能够大概的查看Thread类的结构。咱们看能够看到四个构造函数。咱们经常用到只是俩个:Thread(ParameterizedThreadStart start)和Thread(ThreadStart start)。刚刚看到的时候我一直觉得ThreadStart会跟JAVA的Runnable接口同样子。只到按F12进入查看一下结构才明白大错特错。以下代码spa
C#:线程
[ComVisible(true)] public delegate void ThreadStart();
C#:code
[ComVisible(false)] public delegate void ParameterizedThreadStart(object obj);
咱们能够清楚的看到一个关键字delegate。相信有看过上一章的朋友都知道他是跟事件有关系。没有错。就是定义一个委托类型。以便未来用于传方法。因此咱们能够明白这边的Thread类的构造函数的参数只能传入方法。那么相信笔者上面的三个线程的定义的意义也很明显了。对象
myThread1线程:笔者用的是lambda表达式来建立。lambda表达是什么上一章也有简单的讲到。blog
myThread2线程:外面定义一个方法用于实现多线程。这方法能够是一个静态方法也能够是一个对象的方法。关键字static的功能跟JAVA同样子。
myThread3线程:实现有一个有参数的多线程。
上面只是讲到关于Thread类的使用。对于Thread类对象里面的一些方法的话,笔者就很少介绍了。大至跟JAVA的Thread类同样子。如Interrupt方法。请读者们自行查看。
ThreadPool类 |
当咱们谈到多线程池的时候,相信你们都知道是什么东西。C#用的是ThreadPool类。只是惋惜笔者在JAVA这边用到多线程池的机会很少。因此也不清楚JAVA中的ThreadPoolExecutor类和Executors类跟C#的ThreadPool类相差多少。不过有兴趣的朋友能够看一下。笔者这里仍是讲一下ThreadPool类的使用吧。ThreadPool类更多的时候有一点像工具类同样子。以下面代码。
C#:
class Program { static void Main(string[] args) { ThreadPool.QueueUserWorkItem((obj) => { Console.WriteLine("这是一个lambda表达式建立有参数的线程 参数:" + obj.ToString()); }); ThreadPool.QueueUserWorkItem(WaitCallbackImp); } public static void WaitCallbackImp(object obj) { Console.WriteLine("这是一个用方法建立线程"); } }
上面的代码跟上面的Thread类有一点相似。但是本质上却有很大的差异。这里是用多线程池的。另外对于多线程池的设置。只要ThreadPool.XXXXX里面有不少方法让你去设置。
Task类 |
若是大家有用上面的Thread类你就会发现,有时候当线程在运行中的时候很难中止。可是若是你用了Task类的话,你就会发现这个难点已经不存在了。我也不清楚C#为何会引入Task类。可能就是由于Thread类和ThreadPool类太难控制吧。那么这不是笔者关注的问题。让咱们看一下Task类是如何使用的。Task类是中文经常叫作任务。因此就是有一种说法。是单任务仍是多任务。为何笔者会这样子讲呢?以下。
1.单任务。便是一个Task类实例。这个时候就比较简单。代码以下
class Program { static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource();//用于中途取消 Task myTask = new Task((obj) => { Console.WriteLine("这是一个单任务"); }, cts); myTask.Start(); Console.ReadKey(); } }
这里面笔者只用到了一个类CancellationTokenSource。这个类就是用于取消任务。仍是让笔者写一个例子吧。
class Program { static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource();//用于中途取消 Task myTask = new Task((obj) => { Console.WriteLine("这是一个单任务"); Thread.Sleep(20000);//让他睡一段时间 }, cts); myTask.Start(); if (cts.IsCancellationRequested)//判断是否取消 { cts.Cancel(); } Console.ReadKey(); } }
2.多任务。就是多个Task类的实例进行配合。这个时候就有谁先作。谁后作的问题。
class Program { static void Main(string[] args) { CancellationTokenSource cts1 = new CancellationTokenSource();//用于中途取消 Task myTask1 = new Task((obj) => { Console.WriteLine("这是一个单任务"); //Thread.Sleep(20000);//让他睡一段时间 }, cts1); CancellationTokenSource cts2 = new CancellationTokenSource();//用于中途取消 myTask1.ContinueWith((task) => { Console.WriteLine("myTask2任务"); }, cts2.Token); myTask1.Start(); //if (cts1.IsCancellationRequested)//判断是否取消 //{ // cts1.Cancel(); //} Console.ReadKey(); } }
上面的ContinueWith方法就是表示:当myTask1结束以后,就能够继续红色的代码。便是另外一个Task任务。除了上面的实例以后,还有一种用法。代码以下。
CancellationTokenSource cts3 = new CancellationTokenSource();//用于中途取消 Task.Factory.StartNew((obj) => { Console.WriteLine("这是一个用的Factory单任务"); }, cts3);
看样了不用笔者多说了。有一点相似于多线程池的概念。只是注意Task.Factory里面还有一些很好用的功能。ContinueWhenAll方法就是一个很好的体现。和上面的ContinueWith有一个像。便是因此的task结束以后才执行对应的最后一个task。请用Task.Factory.让他提示进行学习。若是不提示的话,写完上面的"ask.Factory."以后按Ctrl+J。里面有各类方法让你学习。
本章总结 |
本章主要是对多线程经常使用的一些知识进行讲解。笔者并无对他们进行详细的说明。因此但愿读者们能够根据笔者所讲的继续深刻下去。