C# 多线程–菜鸟教程
线程 被定义为程序的执行路径。每个线程都定义了一个独特的控制流。如果您的应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。
线程生命周期
线程生命周期开始于 System.Threading.Thread 类的对象被创建时,结束于线程被终止或完成执行时。
下面列出了线程生命周期中的各种状态:
-
未启动状态:当线程实例被创建但 Start 方法未被调用时的状况。
-
就绪状态:当线程准备好运行并等待 CPU 周期时的状况。
-
不可运行状态:下面的几种情况下线程是不可运行的:
- 已经调用 Sleep 方法
- 已经调用 Wait 方法
- 通过 I/O 操作阻塞
-
死亡状态:当线程已完成执行或已中止时的状况。
主线程
进程中第一个被执行的线程称为主线程。
当 C# 程序开始执行时,主线程自动创建。使用 Thread 类创建的线程被主线程的子线程调用。您可以使用 Thread 类的 CurrentThread 属性访问线程。
下面的程序演示了主线程的执行:
实例
using System ;
using System.Threading ;
namespace MultithreadingApplication
{
class MainThreadProgram
{
static void Main ( string [ ] args )
{
Thread th = Thread . CurrentThread ;
th . Name = “MainThread” ;
Console . WriteLine ( “This is {0}”, th . Name ) ;
Console . ReadKey ( ) ;
}
}
}
当上面的代码被编译和执行时,它会产生下列结果:
This is MainThread
创建线程
线程是通过Thread 类创建的。Thread 类调用 Start() 方法来开始子线程的执行。
下面的程序演示了这个概念:
using System;
using System.Threading;
namespace MultithreadingApplication
{
class ThreadCreationProgram
{
public static void CallToChildThread()
{
Console.WriteLine("Child thread starts");
}
static void Main(string[] args)
{
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
}
当上面的代码被编译和执行时,它会产生下列结果:
In Main: Creating the Child thread
Child thread starts
管理线程
Thread 类提供了各种管理线程的方法。
下面的实例演示了 sleep() 方法的使用,用于在一个特定的时间暂停线程。
using System;
using System.Threading;
namespace MultithreadingApplication
{
class ThreadCreationProgram
{
public static void CallToChildThread()
{
Console.WriteLine("Child thread starts");
// 线程暂停 5000 毫秒
int sleepfor = 5000;
Console.WriteLine("Child Thread Paused for {0} seconds",
sleepfor / 1000);
Thread.Sleep(sleepfor);
Console.WriteLine("Child thread resumes");
}
static void Main(string[] args)
{
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
}
当上面的代码被编译和执行时,它会产生下列结果:
In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes
销毁线程
Abort() 方法用于销毁线程。
通过抛出 threadabortexception 在运行时中止线程。这个异常不能被捕获,如果有 finally 块,控制会被送至 finally 块。
这个异常不能被捕获是什么鬼,可以被捕获呀
下面的程序说明了这点:
using System;
using System.Threading;
namespace MultithreadingApplication
{
class ThreadCreationProgram
{
public static void CallToChildThread()
{
try
{
Console.WriteLine("Child thread starts");
// 计数到 10
for (int counter = 0; counter <= 10; counter++)
{
Thread.Sleep(500);
Console.WriteLine(counter);
}
Console.WriteLine("Child Thread Completed");
}
catch (ThreadAbortException e)
{
Console.WriteLine("Thread Abort Exception");
}
finally
{
Console.WriteLine("Couldn't catch the Thread Exception");
}
}
static void Main(string[] args)
{
ThreadStart childref = new ThreadStart(CallToChildThread);
Console.WriteLine("In Main: Creating the Child thread");
Thread childThread = new Thread(childref);
childThread.Start();
// 停止主线程一段时间
Thread.Sleep(2000);
// 现在中止子线程
Console.WriteLine("In Main: Aborting the Child thread");
childThread.Abort();
Console.ReadKey();
}
}
}
当上面的代码被编译和执行时,它会产生下列结果:
In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn’t catch the Thread Exception
C# 多线程–爱整理
一、利用多线程提高程序性能
本节导读:
随着硬件和网络的高速发展,为多线程(Multithreading)处理并行任务,提供了有利条件。
其实我们每时每刻都在享受多线程带来的便利,多核处理器多线程工作、Windows操作系统、Web服务器都在使用多线程工作。
使用多线程直接提高了程序的执行效率,因此学习多线程对提高程序运行能力非常必要,本节主要介绍多线程原理及.NET中多线程在.NET面向对象程序设计中的应用。
1. 关于多线程
在介绍多线程之前,先了解一下进程。
进程:独立运行的程序称为进程。(比如Windows系统后台程序,也可以称为后台进程)
线程:对于同一个程序分为多个执行流,称为线程。
多线程:使用多个线程进行多任务处理,称为多线程。
并发是针对于单核处理器而言,但是目前市场上的CPU是多核的(一个芯片多个CPU核心),多线程设计可以让多个任务分发到多个CPU上并行执行,可以让程序更快的执行。但是并发通常是提高运行在单核处理器上的程序的性能。这么说感觉有点违背直觉,因为在单核处理器上运行并发程序开销要比顺序执行该程序的开销要大(从上到下顺序执行程序),因为并发程序中增加了上下文切换的代价(一个线程切换到另外一个线程),从表面上看如果顺序执行所有程序反而节省了上下文切换的代价。 让这个问题变得不同的是阻塞,程序中的某个任务因为该程序控制范围之外的一些条件(通常是I/O),整个程序就会停止下来,直到外部条件发生变化。此时多线程的优势就会体现出来了,其他任务可以通过获得CPU时间而继续执行,而不会让整个程序停下来。从性能的角度来看,如果没有线程阻塞,那么在单核处理器上使用并发那将毫无意义。
2. 如何合理使用多线程?
A.对于用户等待程序处理时,可以使用多线程处理耗时任务;
B.对于一些不需要即时完成的任务,可以使用后台任务线程处理;
C.对于多并发任务,可以使用多线程同时处理;
这一句的意思是让并发线程变成并行线程吗即让原本是单核处理多个线程,变成多核处理多个线程(一核分配一个线程)
D.对于通讯类,比如对线程阻塞,可以使用多线程。
除过上面的几个常用的情况,还有很多情况下可以使用多线程。
3. 多线程的缺点
线程自然也有缺点,以下列出了一些:
A.如果有大量的线程,会影响性能,因为操作系统需要在他们之间切换;
B.更多的线程需要更多的内存空间;
C.线程会给程序带来更多的bug,因此要小心使用,比如:线程任务在执行完成后,要及时释放内存;
D.线程的中止需要考虑其对程序运行的影响。
4. .NET中的两种多线程
.NET本身就是一个多线程的的环境。
在.NET中有两种多线程的:
一种是使用Thread类进行线程的创建、启动,终止等操作。
一种是使用ThreadPool类用于管理线程池.
5 .NET中使用Thread进行多线程处理
线性池是一种多线程并发的处理形式,它就是由一堆已创建好的线程组成。有新任务 -> 取出空闲线程处理任务 -> 任务处理完成放入线程池等待。避免了处理短时间任务时大量的线程重复创建、销毁的代价,非常适用于连续产生大量并发任务的场合。
5.1 Thread类常用方法
.NET基础类库的System.Threading命名空间提供了大量的类和接口支持多线程。System.Threading.Thread类是创建并控制线程,设置其优先级并获取其状态最为常用的类。
下面是该类几个至关重要的方法: Thread.Start():启动线程的执行; Thread.Suspend():挂起线程,或者如果线程已挂起,则不起作用; Thread.Resume():继续已挂起的线程; Thread.Interrupt():中止处于Wait或者Sleep或者Join线程状态的线程; Thread.Join():阻塞调用线程,直到某个线程终止时为止 Thread.Sleep():将当前线程阻塞指定的毫秒数; Thread.Abort():终止此线程。如果线程已经在终止,则不能通过Thread.Start()来启动线程。
suspend 挂起、暂停 resume 继续、重新开始 interrupt 中断、打断
5.2 Thread类常用属性
Thread的属性有很多,我们先看最常用的几个:
CurrentThread :用于获取当前线程;
ThreadState 当前线程的状态(5.4介绍);
Name&