2009年9月29日星期二

multithread 多线程

C#中提供了4种方式实现多线程,各有优缺点

1.thread
可以暂停,重开,终止,但是反复的生成和终止线程会导致性能下降。
新开线程的函数中,不能有参数也不能有返回值。
2.ThreadPool 线程池
能高效的同时运行多个线程。
线程函数只能设置一个object型的参数。
不能有返回值。
线程的暂停,终止等控制困难。
同时能执行的线程的数量有限。
3.delegate 代理
函数可以有参数和返回值,和普通函数的调用无异,线程的终止,暂停等控制困难,同时执行的线程数有限制。
4.Timer
一定时间间隔执行函数,但是随同时执行的函数的增多,性能急剧下降。

下面分别用例子说明各个多线程的实现方式

例1 用thread类实现多线程

using System;
using System.Threading;

public class List1_1
{
public static void Main()
{
Thread threadA = new Thread(
new ThreadStart(ThreadMethod)); //

threadA.Start(); //

for(int i = 0; i < 100; i++)
{
Thread.Sleep(5);
Console.Write(" B ");
}
}

// 线程函数 注意:不能有参数也不能有返回值
private static void ThreadMethod()
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(5);
Console.Write(" A ");
}
}
}

由于线程函数不能传递参数,为应用带来了很大的不便,为了解决这个问题,实际应用中做一个线程类,利用类内部的属性字段来实现参数的传递,看下面的例子

using System;
using System.Threading;

public class List1_2
{
public static void Main()
{
ThreadedTextPrinter printer = new ThreadedTextPrinter(); //
printer.Print("A"); //

for (int i = 0; i < 100; i++)
{
Thread.Sleep(5);
Console.Write(" B ");
}
}
}

public class ThreadedTextPrinter //
{
private string text;

public void Print(string s) //
{
text = s; //

Thread thread = new Thread(new ThreadStart(ThreadMethod));
thread.Start();
}

//线程函数
private void ThreadMethod() //
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(5);
Console.Write(" {0} ", text); //
}
}
}


thread类的属性

thread.IsBackground = true; //后台执行
thread.Priority = ThreadPriority.Highest; //优先级别
thread.Suspend(); // 暂停
thread.Resume(); //继续
thread.Join();//等待到终了
thread.Abort();//强制终止
thread.Sleep(1000);//等待1秒

例2 ThreadPool 线程池

using System;
using System.Threading;

public class List2
{
public static void Main()
{
//为了让ThreadMethod在线程池中执行,需要定义WaitCallback型代理变量
WaitCallback waitCallback
= new WaitCallback(ThreadMethod); //

// 将线程函数登录进线程池
ThreadPool.QueueUserWorkItem(waitCallback, "A"); //
ThreadPool.QueueUserWorkItem(waitCallback, "B"); //

//在有按键输入前,程序一直运行。否则程序刚运行就结束,什么反应都没有。
Console.ReadLine();
}

// 线程函数 注意:可以有一个object型的参数,不能有返回值
private static void ThreadMethod(object state) //
{
for (int i = 0; i < 100; i++)
{
Thread.Sleep(5);
Console.Write(" {0} ", state);
}
}
}

线程池中同时执行的线程数有25的最大限制,ThreadPool.GetAvailableThreads可以返回还有多少线程可用=25-当前线程池中的线程的。

例3 用代理实现的多线程,这个例子理解起来比较难,在代码中加了很多注释。


//包含有返回值和参数的代理(delegate)
//这个代理是用来另起线程用的,所以在结构上和下面的线程函数ThreadMethod完全一致,参数和返回值相同。
delegate DateTime ThreadMethodDelegate(string c); //

static ThreadMethodDelegate threadMethodDelegate; //

public static void Main()
{
//用线程函数作为参数,生成一个代理的实例。
threadMethodDelegate
= new ThreadMethodDelegate(ThreadMethod); //

// 通过代理,开启线程调用,本程序的难点。
//BeginInvoke的参数介绍
//参数1:传给线程函数的参数,即ThreadMethod的参数。如果参数有多个可以顺序指定。
//参数2:异步回调函数,线程函数调用结束后,自动触发该回调函数的调用。
//参数3:object型的对象,可以自由指定。指定的对象作为回调函数的参数,同时也是BeginInvoke的返回值,所以回调函数的参数类型只能是IAsyncResult,如果不想用,可以用Null代替。
threadMethodDelegate.BeginInvoke(".",
new AsyncCallback(MyCallback), DateTime.Now); //

Console.ReadLine();
}

// 线程函数
private static DateTime ThreadMethod(string c)
{
//每过10毫米输出一个c,输出100次。
for (int i = 0; i < 100; i++)
{
Thread.Sleep(10);
Console.Write(c);
}
return DateTime.Now;
}


// 线程处理结束后,自动触发执行的回调函数。
private static void MyCallback(IAsyncResult ar) //
{

//为了取得线程函数的返回值,调用EndInvoke()。
DateTime result = threadMethodDelegate.EndInvoke(ar); // ThreadMethod的返回值
//参见BeginInvoke()的第3个参数
DateTime beginTime = (DateTime)ar.AsyncState; // DateTime.Now

Console.WriteLine();
Console.WriteLine(
"{0} 处理开始、{1}处理结束。",
beginTime, result);
}



执行结果:

................................................................................
....................
2009/09/29 16:58:38 处理开始、2009/09/29 16:58:40处理结束。

例4 用Timer实现的多线程

using System;
using System.Threading;

public class List4
{
public static void Main()
{
//TimerCallback类型的回调函数,这个函数将会每经过一段时间被调用一次。
TimerCallback timerCallback
= new TimerCallback(ThreadMethod); //

// 显示当前时刻
Console.WriteLine(DateTime.Now);

//等待5秒,每2秒调用一次timerCallback
//调用一次timerCallback,等待5秒,然后每过2秒调用一次timerCallback。
//第二个参数 可以作为timerCallback的参数使用,object类型。
Timer timer = new Timer(
timerCallback, null, 5 * 1000, 2 * 1000); //

Console.ReadLine();
}

// 每2秒执行一次的线程函数
private static void ThreadMethod(object state) //
{
Console.WriteLine(DateTime.Now);
}
}

没有评论:

发表评论