线程实用解析--------(二)创建调用有参函数的线程和线程池简介

来源:互联网 发布:正装 知乎 编辑:程序博客网 时间:2024/05/27 20:51

     上一节主要是对线程有一个具体的介绍,同时也介绍了线程调用无参函数的方法,这一节主要介绍线程调用有参甚至是多参函数,同时也会进一步的介绍线程池。

     先介绍线程调用有参函数

     一、调用有一个参数的函数

static void Main(string[] args)

        {

            //标记显示主线程ID   

            Console.WriteLine("主线程的ID:" + Thread.CurrentThread.ManagedThreadId);

            //如果线程要调用有参函数,这时线程的构造函数的参数应为一个ParameterizedThreadStart的实例对象,函数参数必须为Object类型

            Thread thread = new Thread(new ParameterizedThreadStart(ParamMethod));                                  

            thread.Start("Olive");

           //同时还可以用lambda表达式进行传值,这个时候可以传任意类型的值和任意多个参数

            Thread thread1=new Thread(()=>ParamMethod("Olive");

            Thread1.Start();

            Console.ReadKey();

        }

        private static void ParamMethod(object name)

        {

            Console.WriteLine("当前的线程ID:" + Thread.CurrentThread.ManagedThreadId);//标记显示当前线程ID

            Console.WriteLine("Hello WorldMy gril's name is:" + name); 

        }

效果如图

二、调用有多个参数的构造函数

线程调用含有多个参数的函数主要有以下几种方法。

1、将所需要的传递的数据封装成一个类

 例如:

       先建一个类,将要传递的信息包含其中

 public class Student

    {

        public string Name

        { get;  set; }

        public string Sex

        { get;  set; }

        public int Age

        { get;  set; }

        public string Address

        { get; set;}

}

具体的实现如下:

static void Main(string[] args)

        {

       Student student = new Student()

            {

                Name = "Olve",

                Sex = "",

                Age = 22,

                Address = "北京"

            };

            Console.WriteLine("主线程的ID:" + Thread.CurrentThread.ManagedThreadId);//标记显示主线程ID

            Thread thread = new Thread(new ParameterizedThreadStart(ParamMethod));

            thread.Start(student);

            Console.ReadKey();

        }

private static void ParamMethod(object obj)

        {

            Console.WriteLine("当前的线程ID:" + Thread.CurrentThread.ManagedThreadId);//标记显示当前线程ID

            Student student = (Student)obj;//因为传递的参数为Object类型的这里要强制转换下

            Console.WriteLine("Hello WorldMy gril's name is  " + student.Name);

            Console.WriteLine("and her age is "+student.Age);

            Console.WriteLine("Now,She is in "+student.Address);

        }

2、使用lambda表达式传递多个参数

   通过使用lambda表达式传递多个参数和传递一个参数是一样的

具体看代码

Main函数里代码:

Thread thread=new Thread(()=>TestShow("Olive","22","北京"));

thread.Start();

Private static void (object name,object age,object address)

{

 Console("My girl's name is"+name+"Age is"+age+"Address is"+address);

效果如下图:

介绍完了线程调用有参函数的传参,下面再介绍下线程池。

创建线程是需要时间的,每个线程也会被分配一些内存。许多应用程序一般都使用多个线程进行协同工作,为了简化对这些线程的管理,.NET框架为每一个进程提供了一个线程池,使应用程序能够根据需要来有效地利用多个线程。线程池线程都是后台线程。每个线程都使用默认堆栈大小,以默认的优先级运行,并处于多线程单元中。

在这里首先要感谢下上一节中给我指出错误的兄弟,实在是抱歉由于我的一时疏忽,将通过Thread类创建的线程写成是后台线程,这确实是大错特错的。先介绍下什么是前台线程、什么是后台线程。

前台线程:线程默认为前台线程,只要有一个前台线程在运行,程序就一直运行、存活。

后台线程:当所有的前台线程结束之后,程序就会结束,不论后台线程是否运行结束,程序都会将后台线程给Kill掉。 

在默认情况下,用Thread 类创建的线程都是前台线程。线程池中的线程总是后台线程.

在用Thread类创建线程时,可以设置属性IsBackground,以确定该线程是(false)前台线程还是(true)后台线程。一般使用时多将线程设置为后台线程,这样在程序关闭时可以立即释放资源,有时候我们会发现明明一个程序已经关闭了,但是查看任务管理器发现它还在占用一些内存,就是因为还有些前台线程没有执行完毕的缘故。

线程池特别适合于执行一些需要多个线程的任务。使用线程池能够优化这些任务的执行过程,从而提高吞吐量,它不仅能够使系统针对此进程优化该执行过程,而且还能够使系统针对计算机上的其他进程优化该执行过程。但是同时它也有一些限制比如:不能把线程池中的线程改为前台线程,不能给线程池中的线程设置优先级或名称,线程池中的线程只能用于时间较短的任务,如果用时较长,应使用Thread类创建实例。

下面介绍线程池的主要用法:

System.Threading.ThreadPool类实现了线程池,该类是一个静态类。最长用的是

ThreadPool.QueueUserWorkItem(WaitCallback waitcallback ,object state)

该函数有两个参数一个是WaitCallBack类型的委托,一个是状态,可以作为传递单个的参数,如果需要传递多个参数,可以先将参数封装成类,传递类对象。

ThreadPool.QueueUserWorkItem方法在线程池中创建一个线程池线程来执行指定的方法(用委托WaitCallback来表示),并将该线程排入线程池的队列等待执行

具体使用如下:

Main函数代码如下:

{

            string s="Olive";

            ThreadPool.QueueUserWorkItem(new WaitCallback(Count), s);

}

Private static Count(object name)

{

  Console.WriteLine("Hello ! My Name is  "+name);

}

每个进程都有且只有一个线程池。当进程启动时,线程池并不会自动创建。当第一次将回调方法排入队列(比如调用ThreadPool.QueueUserWorkItem方法)时才会创建线程池。

这一节就介绍到这里了,下一节会介绍线程的同步相关的知识。希望能对朋友们有一点帮助,如果有说的不对的地方,还请各位多多指教!