天天看点

C#基础系列——多线程的常见用法详解

前言:前面几节分别介绍了下C#基础技术中的反射、特性、泛型、序列化、扩展方法、Linq to Xml等,这篇跟着来介绍下C#的另一基础技术的使用。最近项目有点紧张,所以准备也不是特别充分。此篇就主要从博主使用过的几种多线程的用法从应用层面大概介绍下。文中观点都是博主个人的理解,如果有不对的地方望大家指正~~

1、多线程:使用多个处理句柄同时对多个任务进行控制处理的一种技术。据博主的理解,多线程就是该应用的主线程任命其他多个线程去协助它完成需要的功能,并且主线程和协助线程是完全独立进行的。不知道这样说好不好理解,后面慢慢在使用中会有更加详细的讲解。

2、多线程的使用:

(1)最简单、最原始的使用方法:Thread oGetArgThread = new Thread(new ThreadStart(() =>{});这种用法应该大多数人都使用过,参数为一个ThreadStart类型的委托。将ThreadStart转到定义可知:

它是一个没有参数,没有返回值的委托。所以他的使用如下:

    for (var i = 0; i < 1000000; i++)

    {

      Console.WriteLine("主线程计数" + i);

      //Thread.Sleep(100);

    }

定义一个没有参数没有返回值的方法传入该委托。当然也可以不定义方法写成匿名方法:

这个和上面的意义相同。得到的结果如下:

C#基础系列——多线程的常见用法详解

说明主线程和后台线程是互相独立的。由系统调度资源去执行。

如果这样那有人就要问了,如果我需要多线程执行的方法有参数或者有返回值或者既有参数又有返回值呢。。。别着急我们来看看new Thread()的几个构造函数:

转到定义可知参数有两类,一类是无参无返回值的委托,另一类是有参无返回值的委托。对于有参数的委托使用方法:

对于有参又有返回值的委托,很显然使用new Thread()这种方式是没有解决方案的。其实对于有参又有返回值的委托可以使用异步来实现:

关于这种方式还有几点值得一说的是:

①Thread oGetArgThread = new Thread(new ThreadStart(Test));

oGetArgThread.Join();//主线程阻塞,等待分支线程运行结束,这一步看功能需求进行选择,主要为了多个进程达到同步的效果

②线程的优先级可以通过Thread对象的Priority属性来设置,Priority属性对应一个枚举:

从0到4,优先级由低到高。

③关于多个线程同时使用一个对象或资源的情况,也就是线程的资源共享,为了避免数据紊乱,一般采用.Net悲观锁lock的方式处理。

(2)Task方式使用多线程:这种方式一般用在需要循环处理某项业务并且需要得到处理后的结果。使用代码如下:

使用这种方式的时候需要注意这一句 var bdTmp = bd;这里必须要用一个临时变量,要不然多个bd对象容易串数据。如果有兴趣可以调试看看。这种方法比较简单,就不多说了。当然Task对象的用法肯定远不止如此,还涉及到任务的调度等复杂的逻辑。博主对这些东西理解有限,就不讲解了。

(3)线程池的用法:一般由于考虑到服务器的性能等问题,保证一个时间段内系统线程数量在一定的范围,需要使用线程池的概念。大概用法如下:

需要注意:Semaphore对象的数量需要根据服务器的性能来设定;System.Threading.Tasks.Parallel.ForEach这种方式表示同时启动lstTestBed.Length个线程去做一件事情,可以理解为

(4) 多线程里面还有一个值得一说的SpinWait类,用于提供对基于自旋的等待的支持。也就是说支持重复执行一个委托,知道满足条件就返回,我们来看它的用法:

这个方法有三个构造函数,后两个需要传入一个时间,表示如果再规定的时间内还没有返回则自动跳出,防止死循环。

博主使用过的多线程用法大概就这么三大类,当然这些其中还涉及很多细节性的东西,博主原来使用这些的时候经常出现各种莫名的问题,可能还是没用好的原因,对这些东西理解还不够深刻。如果大家也遇到类似的问题可以拿出来探讨!!

多线程用法示例

继续阅读