C#中多线程应用
来源:互联网 发布:网络教育交通大学 编辑:程序博客网 时间:2024/05/02 08:25
介绍
线程是轻量级的进程。使用线程能提供应用系统的效率。为了使用多线程需要引入System命名空间中的Threading命名空间。System.Threading命名空间包含需要使用多线程的地方。现在让我们来看第一个程序。
示例分析
示例1(Program01.cs)
using System;
using System.Threading;
public class MyThread {
public staticvoid Thread1() {
for (inti = 0; i < 10; i++) {
Console.WriteLine("Thread1 {0}", i);
}
}
public staticvoid Thread2() {
for (inti = 0; i < 10; i++) {
Console.WriteLine("Thread2 {0}", i);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
Threadtid1 = new Thread(new ThreadStart(MyThread.Thread1));
Threadtid2 = new Thread(new ThreadStart(MyThread.Thread2));
tid1.Start();
tid2.Start();
}
}
开始探索整个程序。
这个程序有一个MyThread类包括两个静态方法Thread1和Thread2。为了创建线程需要创建Thread类对象。Thread类的构造方法是ThreadStart的引用。这个构造方法可能会发出两种类型的异常;当参数是一个空引用时引发ArgumentNullException异常或当程序不允许创建线程的SecurityException异常。
Thread类的参数是ThreadStart的引用。当线程开始时执行ThreadStart指向的方法。ThreadStart的参数名是函数名,作为线程的函数。Thread1是一个静态方法可以使用类名来访问不需要要创建类的对象。线程开始执行Thread类的Start()方法。下面是程序的输出:
Before start thread
Thread1 0
Thread1 1
Thread1 2
Thread1 3
Thread1 4
Thread1 5
Thread1 6
Thread1 7
Thread1 8
Thread1 9
Thread2 0
Thread2 1
Thread2 2
Thread2 3
Thread2 4
Thread2 5
Thread2 6
Thread2 7
Thread2 8
Thread2 9
线程的方法可以不是静态方法。在下面的例子中使用非静态方法需要创建类的对象。
示例2(Program02.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Console.WriteLine("Thread1 {0}", i);
}
}
public voidThread2() {
for (inti = 0; i < 10; i++) {
Console.WriteLine("Thread2 {0}", i);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr.Thread1));
Threadtid2 = new Thread(new ThreadStart(thr.Thread2));
tid1.Start();
tid2.Start();
}
}
这个程序的输出和上一个的输出相同。
不需要为两个线程创建两个方法。可以使用一个方法为两个线程类创建两个线程。看下面的程序。
示例3(Program03.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Console.WriteLine("Helloworld {0}", i);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1));
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1));
tid1.Start();
tid2.Start();
}
}
这里创建了两个MyThread对象执行两个线程。
在构造方法传递参数时也不需要创建ThreadStart对象。可以创建ThreadStart对象并将它传递给Thread参数。看下面的程序。
示例4(Program04.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Console.WriteLine("Hello world {0}", i);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
ThreadStart tStart1 = new ThreadStart(thr1.Thread1);
ThreadStart tStart2 = new ThreadStart(thr2.Thread1);
Threadtid1 = new Thread(tStart1);
Threadtid2 = new Thread(tStart2);
tid1.Start();
tid2.Start();
}
}
这个程序也有相同的输出。
Sleep方法在指定的时间范围内挂起线程。Sleep是静态方法使用时不需要创建Thread线程。有两个重载的Sleep()方法,一个是指定时间的毫秒数,另一个是TimeSpan结构的实例。
示例5(Program05.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Console.WriteLine("Hello world " + i);
Thread.Sleep(1);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Start();
tid2.Start();
}
}
这个线程休眠1秒并给第二个线程一个机会执行。下面是输出结果:
Before start thread
Hello world 0
Hello world 0
Hello world 1
Hello world 1
Hello world 2
Hello world 2
Hello world 3
Hello world 3
Hello world 4
Hello world 4
Hello world 5
Hello world 5
Hello world 6
Hello world 6
Hello world 7
Hello world 7
Hello world 8
Hello world 8
Hello world 9
Hello world 9
看似这两个线程是并行执行的。下面程序将显示重载的Sleeep方法。
示例6(Program06.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
intiHour = 0;
intiMin = 0;
intiSec = 1;
Console.WriteLine("Hello world " + i);
Thread.Sleep(new TimeSpan(iHour, iMin, iSec) );
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Start();
tid2.Start();
}
}
TimeSpan结构有四个重载的构造方法。第一个是参数为长整型的指定特殊值,第二个有3个整型参数分别表示时、分、秒,第3个有4个整型参数分别表示日、时、分、秒,第4个构造方法有5 个参数表示日、时、分、秒和毫秒。这个程序和上面的程序打印一秒钟打印一次新值外其他的相同。
Sleep方法抛出3中类型的异常:当时间值小于0时将引发ArgumentException异常,当休眠线程中断时引发ThreadInterruptedException异常,当不适当的时候调用方法将引发SecurityException异常。
下面程序显示执行情况下Sleep()方法是负面的。
示例7(Program07.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
intiHour = 0;
intiMin = 0;
intiSec = -1;
try {
Console.WriteLine("Hello world " + i);
Thread.Sleep(new TimeSpan(iHour, iMin, iSec) );
}catch (ArgumentException ae) {
Console.WriteLine(ae.Message );
}
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Start();
tid2.Start();
}
}
Message是ArgumentException类的一个属性用来描述异常信息。在这个程序中会给出如下错误信息。
Parameter Name: Argument must be greater than 0 and less than2^31 - 1milliseconds.
也可以通过Thead类的Name属性通过线程的名称来访问线程。
示例8(Program08.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(thr.Name + "=" + i);
Thread.Sleep(1);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Beforestart thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Name= "Thread 1";
tid2.Name= "Thread 2";
tid1.Start();
tid2.Start();
}
}
为了防止应用程序崩溃可以在可能发生异常的地方捕获异常。可能在Sleep方法中抛出异常,可以用try来捕获所有的异常。
示例9(Program09.cs)
using System;
using System.Threading;
using System.Security;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(thr.Name + "=" + i);
try {
Thread.Sleep(1);
}catch (ArgumentException ae) {
Console.WriteLine(ae.ToString() );
}catch (ThreadInterruptedException tie) {
Console.WriteLine(tie.ToString() );
}catch (SecurityException se) {
Console.WriteLine(se.ToString() );
}
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Name= "Thread 1";
tid2.Name= "Thread 2";
tid1.Start();
tid2.Start();
}
}
这个程序捕获了三个异常。看这段代码的第一行。多用了一个命名空间:System.Security。SecurityException异常类定义在这个命名空间。
在创建线程实例的方法中为线程命名。可以通过CurrentThread获得线程的名称。CurrentThread是线程类的静态方法。当调用者不适合安全访问这个属性抛出的一个异常:SecurityException。
程序的运行结果:
Before start thread
Thread 1=0
Thread 2=0
Thread 1=1
Thread 2=1
Thread 1=2
Thread 2=2
Thread 1=3
Thread 2=3
Thread 1=4
Thread 2=4
Thread 1=5
Thread 2=5
Thread 1=6
Thread 2=6
Thread 1=7
Thread 2=7
Thread 1=8
Thread 2=8
Thread 1=9
Thread 2=9
可以使用Abort()终止线程。Abort有两个重载方法。第一个是执行没有参数的方法,第二个是带有Object参数的方法。这个方法抛出ThreadAbortException异常没有被捕获。看下面的程序:
示例10(Program10.cs)
using System;
using System.Threading;
using System.Security;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(thr.Name + "=" + i);
try {
Thread.Sleep(1);
}catch (ArgumentException ae) {
Console.WriteLine(ae.ToString() );
}catch (ThreadInterruptedException tie) {
Console.WriteLine(tie.ToString());
}catch (SecurityException se) {
Console.WriteLine(se.ToString() );
}
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Name= "Thread 1";
tid2.Name= "Thread 2";
tid1.Start();
tid2.Start();
try {
tid1.Abort();
tid2.Abort();
} catch(ThreadAbortException tae) {
Console.WriteLine(tae.ToString() );
}
Console.WriteLine("End of Main");
}
}
程序输出:
Before start Thread
End of Main
这个输出结果很明显的表面线程没有执行。一个线程终止后就不能在开始。看下面的程序。
示例11(Program11.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(thr.Name + "=" + i);
Thread.Sleep(1);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Name= "Thread 1";
tid2.Name= "Thread 2";
tid1.Start();
tid2.Start();
tid1.Abort();
tid2.Abort();
Console.WriteLine("After Abort");
tid1.Start();
tid2.Start();
Console.WriteLine("End of Main");
}
}
这个程序抛出一个System.Threading.ThreadStateException异常。现在使用异常捕获后关闭程序而不是用异常终止。
示例12(Program12.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (int i = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(thr.Name + "=" + i);
Thread.Sleep(1);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Name= "Thread 1";
tid2.Name= "Thread 2";
try {
tid1.Start();
tid2.Start();
} catch(ThreadStateException te) {
Console.WriteLine(te.ToString() );
}
tid1.Abort();
tid2.Abort();
try {
tid1.Start();
tid2.Start();
} catch(ThreadStateException te) {
Console.WriteLine(te.ToString() );
}
Console.WriteLine("End of Main");
}
}
这里捕获ThreadStatException异常并用这个类的ToString方法。ToString方法返回一个异常的全缀名,和可能的错误信息,异常内部名和堆跟踪信息。
可以用Join方法来等待终端的线程。这个方法有三个重载方法。第一个没有参数等待仍然逝去的线程,第二个是带有一个int参数在期待的时间内等待逝去的线程,第三个是带TimeSpan结果的引用,看下面的程序。
示例13(Program13.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(thr.Name + "=" + i);
Thread.Sleep(1);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Name= "Thread 1";
tid2.Name= "Thread 2";
try {
tid1.Start();
tid2.Start();
} catch(ThreadStateException te) {
Console.WriteLine(te.ToString() );
}
tid1.Join();
tid2.Join(new TimeSpan(0, 0, 1) );
Console.WriteLine("End of Main");
}
}
程序等等第一个线程知道他完成为止第二个线程等待1秒。
线程执行有两种方法:后台和前台。当应用程序终止时后台线程完成,另一个前台线程不等的应用程序终止。设置线程执行使用IsBackground属性。下面程序显示了这个用法。
示例14(Program14.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(thr.Name + "=" + i);
Thread.Sleep(1);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Name= "Thread 1";
tid2.Name= "Thread 2";
tid1.IsBackground = true;
tid2.IsBackground = true;
try {
tid1.Start();
tid2.Start();
} catch(ThreadStateException te) {
Console.WriteLine(te.ToString() );
}
Thread.Sleep(10);
Console.WriteLine("End of Main");
}
}
程序输出:
Before start thread
Thread 1=0
Thread 2=0
Thread 1=1
Thread 2=1
End of Main
输出显示当应用程序终止时两个背景线程也都终止。
也可以为线程设置优先权。可以使用Thread类的ThreadPriority属性来设置线程的优先级。下面程序显示使用线程的属性设置有效级。
示例15(Program15.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
for (inti = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(thr.Name + "=" + i);
Thread.Sleep(1);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
MyThreadthr2 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
Threadtid2 = new Thread(new ThreadStart(thr2.Thread1) );
tid1.Name= "Thread 1";
tid2.Name= "Thread 2";
tid1.Priority = ThreadPriority.Highest;
tid2.Priority= ThreadPriority.Lowest;
try {
tid1.Start();
tid2.Start();
} catch(ThreadStateException te) {
Console.WriteLine(te.ToString() );
}
tid1.Join();
tid2.Join();
Console.WriteLine("End of Main");
}
}
线程1的优先级是Highest线程2是Lowest。另外线程的优先级是AboveNormal, BelowNormal 和 Normal.
GetDomain()方法返回线程执行的执行文件的名。这个静态方法使用类名来访问。
示例16(Program16.cs)
using System;
using System.Threading;
public class MyThread {
public voidThread1() {
Console.WriteLine(Thread.GetDomain() );
for (inti = 0; i < 10; i++) {
Thread thr = Thread.CurrentThread;
Console.WriteLine(i);
}
}
}
public class MyClass {
public staticvoid Main() {
Console.WriteLine("Before start thread");
MyThreadthr1 = new MyThread();
Threadtid1 = new Thread(new ThreadStart(thr1.Thread1) );
tid1.Start();
}
}
程序输出结果:
Before start thread
Name: prog16.exe
No context policies.
0
1
2
3
4
5
6
7
8
9
- C#中多线程应用
- C# 中多线程的应用
- C#多线程应用基础
- C#多线程应用探讨
- C#多线程应用探讨
- C#多线程应用探讨
- C#多线程应用探讨
- C#多线程应用探讨
- C#多线程应用探讨
- C#多线程应用探讨
- C#多线程的应用
- c#中多线程---使用多线程
- C#的WinForm多线程应用
- c#中使用多线程
- c#中使用多线程
- c#中使用多线程
- C#中编写多线程
- C#中多线程问题
- 正人先正己
- 2010年最新PHP类的精缩归纳(转载)
- Asp.Net (C#)如何进行Oracle数据库分页(存储过程)
- 基于PHP开发的虚拟主机管理系统
- 开源或免费虚拟主机管理系统
- C#中多线程应用
- 人工智能复习题
- 开通部落格,顺带测试一下 Windows Live Writer
- RedHat(CentOS)和Ubuntu安装软件命令对比(区别)
- ASP.NET 数据库中插入图片和读取图片
- 移动宽带...呵呵...用上了..
- 【其他】【USACO】The Tamworth Two
- 《嫁给程序员》 第三章 《红楼梦》风波
- Cisco QoS配置说明(CBWFQ/LLQ/PQ/CQ/WFQ)