源码 max 更多 sta 关于 如何使用 关系 中文
本章简言 |
上一章中笔者对 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 进入查看一下结构才明白大错特错。如下代码
C#:
- [ComVisible(true)]
- public delegate void ThreadStart();
C#:
- [ComVisible(false)]
- public delegate void ParameterizedThreadStart(object obj);
我们可以清楚的看到一个关键字 delegate。相信有看过上一章的朋友都知道他是跟事件有关系。没有错。就是定义一个委托类型。以便将来用于传方法。所以我们可以明白这边的 Thread 类的构造函数的参数只能传入方法。那么相信笔者上面的三个线程的定义的意义也很明显了。
myThread1 线程:笔者用的是 lambda 表达式来创建。lambda 表达是什么上一章也有简单的讲到。
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。里面有各种方法让你学习。
本章总结 |
本章主要是对多线程常用的一些知识进行讲解。笔者并没有对他们进行详细的说明。所以希望读者们可以根据笔者所讲的继续深入下去。
Java 进击 C#——语法之多线程
来源: http://www.bubuko.com/infodetail-2081563.html