浅谈C#中的多线程编程[1]

  记录,做到温故而知新。

    一、相关概念:
  
什么是进程?
  当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的。
  
什么是线程?
  
线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。
  
什么是多线程?
  
多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

  多线程的好处:
  
可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。
  
多线程编程有好处,也有不好的地方,如:
  
线程也是对象,需要占用内存,线程越多占用内存越多;
  
多线程需要协调和管理,所以需要CPU时间跟踪线程;
  
线程之间对共享资源的访问会相互影响,必须解决竞用共享资源的问题;
  
线程太多会导致控制太复杂,最终可能带来产生Bug的风险。

   二、Thread类
  
先来理解下Thread类,这是实现多线程编程的基础。Thread类位于System.Threading命名空间,其构造函数为:
  
public Thread(ParameterrizedThreadStart start)
  public Thread(ThreadStart start)
  public Thread(ParameterizedThreadStart start, int maxStackSize)
  public Thread(ThreadStart start, int maxStackSize)
  这些构造函数涉及3种类型的参数:
  
1)ParameterizedThreadStart:是一个委托类型,表示此线程开始执行时要调用的方法,支持向调用的方法传递一个参数。
  
2)ThreadStart:是一个委托类型,表示此线程开始执行时要调用的方法没有参数的委托类型,不支持向调用的方法传递一个参数。
  
3)maxStackSize:表示线程要使用的最大堆栈大小,如果为0刚使用可执行文件的文件头中指定的默认最大堆栈大小。
  
Thread类有几个至关重要的方法,描述如下:
  
Start():启动线程;
  
Sleep(int):静态方法,暂停当前线程指定的毫秒数;
  Abort():通常使用该方法来终止一个线程;
  
Suspend():该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复;
  Resume():恢复被Suspend()方法挂起的线程的执行。

 

  Thread类基本的使用代码如下:
  
 

View Code
using System;
using System.Threading;
namespace ProgrammingCSharp4
{
    
public class Program
    {
        
public static void Main(string[] args)
        {            
            Console.WriteLine(
"[主线程id:{0}]",Thread.CurrentThread.ManagedThreadId);
            Thread thread1 
= new Thread(Print);
            thread1.Start();
            Thread thread2 
= new Thread(PrintEx);
            thread2.Start(
"测试");
            Console.ReadKey(
true);
        }
        
public static void Print()
        {
            
int threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine(
"[当前线程id:{0}]{1}",threadId,DateTime.Now.ToShortTimeString());
        }
        
public static void PrintEx(object obj)
        {
            
int threadId = Thread.CurrentThread.ManagedThreadId;
            Console.WriteLine(
"[当前线程id:{0}]{1}",threadId,obj);
        }
    }
}

  三、线程池的使用
  
C#中,我们可以通过一种叫做“池(Pool)”的技术来优化对象的使用,其原理是预先创建一定数量的对象放在“池”里,在对象被请求的时候,某个对象被从“池”中取出供使用,使用完毕再重新放回“池”中,等待下一次的请求。我们可以自己实现这样的线程池,也可以使用.NET Framework为我们所提供的线程池,它叫做TreadPool,位于System.Threading命名空间。
  
需要注意的是线程池中的线程均为后台线程,即它们的IsBackground属性为True。也就是说在所有的前台线程都已经退出后,ThreadPool中的线程不会让应用程序继续保持运行。
  
所以当我们执行一些简单的、耗时短暂的任务时,才应该使用到线程池,在下面的情况下则不应该使用线程池技术:
  
Ø 当需要创建一个前台线程时;
  
Ø 线程池中的线程都是默认优先级的,因此当需要创建具有特定优先级的线程时就不应该使用线程池;  
  
Ø 当需要某个任务只和特定的线程关联时,因为无法选择执行任务时使用的是哪一个具体的线程;
  
Ø 当需要中止特定的线程时不应使用线程池,它不提供这个功能;
  
Ø 线程执行时间比较长时;

  
要使用ThreadPool中的线程,需要使用TheadPool.QueueUserWorkItem这个静态方法指定线程要调用的方法,该方法有两个重载版本:
  
public static bool QueueUserWorkItem(WaitCallBack callBack)
  public static bool QueueUserWorkItem(WaitCallBack callBack,object state)
  WaitCallBack是一个委托类型,下面是线程池使用的例子:

View Code
using System;
using System.Threading;
namespace AsynchronousSample
{
    
class Program
    {
        
public static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(Counter);
            ThreadPool.QueueUserWorkItem(Counter,
"AsynchronousSample Test");
            Console.WriteLine(
"[Thread ID = {0}]The main thread is started.",Thread.CurrentThread.ManagedThreadId);
            Thread.Sleep(
500);
            Console.WriteLine(
"The main thread is closed."); 
            
            Console.ReadKey(
true);
        }
        
        
private static void Counter(object state)
        {
            Console.WriteLine(
"Counting begins, from 1 to 100:");
            Console.WriteLine(
"the Parameter is:{0}",state);
            
for(int counter = 0 ; counter <100;counter++)
            {
                
if(null==state)
                {
                    Console.WriteLine(
"[Thread ID = {0}] {1}",Thread.CurrentThread.ManagedThreadId,counter);
                }
else
                {
                    Console.WriteLine(
"[Thread ID = {0}] {1}",Thread.CurrentThread.ManagedThreadId,state);
                }
                Thread.Sleep(
100);
            }
        }
    }
}


  未完待续,下次接着复习Thread的相关属性与用法。

 

posted @ 2011-03-09 00:39  卿之  阅读(2113)  评论(3编辑  收藏  举报
无觅相关文章插件,快速提升流量