『每一个不曾起舞的日子,都是对生命的辜负。』—— 尼采
单线程顾名思义,就是只有一个线程。默认情况下,系统为应用程序分配一个主线程,该线程执行程序中以Main方法开始和结束,Main方法代码如下:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();//启用应用程序的可视样式
Application.SetCompatibleTextRenderingDefault(false);//新控件使用GDI+
Application.Run(new Form1());
}
(1)单个应用程序域可以使用多线程来完成以下任务,通过网络与Web服务器和数据库进行通信。
A、执行占用大量时间的操作。
B、区分具有不同优先级的任务。
C、使用户界面可以在将时间分配给后台任务时仍能快速做出响应。
(2)如果在程序中使用了多线程,可能会产生如下问题。
A、系统将为进程、APPDomain对象和线程所需要的上下文信息使用内存。因此,可以创建的进程、APPDomain对象和线程的数目会受到可用内存的限制。
B、跟踪大量的线程将占用大量的处理器时间。如果线程过多,则其中大多数线程都不会产生明显的进度。如果大多数当前线程处于一个进程中,则其他进程中的线程的调度频率就会很低。
C、使用许多线程控制代码执行非常复杂,并可能产生许多bug。
D、销毁线程需要了解可能发生的问题并对那些问题进行处理。
Thread类位于System.Threading命名空间下,System.Threading命名空间提供一些可以进行多线程编程的类和接口。
Thread类主要用于创建并控制线程、设置线程优先级并获取其状态。一个进程可以创建一个或多个线程以执行与该进程关联的部分程序代码,线程执行的程序代码由ThreadStart委托或ParameterizedThreadStart委托指定。
创建一个线程非常简单,只需要将其声明并为其提供线程起始点处的方法委托即可。创建新的线程时,需要使用Thread类,Thread类具有接受一个ThreadStart委托或ParameterizedThreadStart委托的构造函数,该委托包装了调用Start方法时由新线程调用的方法。
线程的挂起与恢复分别可以通过调用Thread类中的Suspend方法和Resume方法实现,
1、Suspend方法
该方法用来挂起线程,如果线程已挂起,则不起作用,语法如下:
public void Suspend()
2、Resume方法
该方法用来继续已挂起的线程,语法如下。
public void Resume()
线程休眠主要通过Thread类的Sleep方法实现,该方法用来将当前线程阻止指定的时间,它有两种重载形式,下面分别进行介绍。
(1)将当前线程挂起指定的时间,语法如下。
public static void Sleep(int millisecondsTimeout)
millisecondsTimeout:线程被阻止的毫秒数。指定零以指示应挂起此线程以使其他等待线程能够执行,指定Infinite以无限期阻止线程。
(2)将当前线程阻止指定的时间,语法如下。
public static void Sleep(TimeSpan timeout)
timeout:线程被阻止的时间量的TimeSpan。指定零以指示应挂起此线程以使其他等待线程能够执行,指定Infinite以无限期阻止线程。
例如:
Thread.Sleep(1000); //ss
终止线程可以分别使用Thread类的Abort方法和Join方法实现,下面对这两个方法进行详细介绍。
1、Abort方法
它的两种重载方式如下:
public void Abort()
public void Abort(Object stateInfo)
stateInfo:一个对象,它包含应用程序特定的信息(如状态),该信息可供正被终止的线程使用。
2、Join方法
它的3种重载方式如下:
public void Join()
public bool Join(int millisecondsTimeout)
public bool Join(TimeSpan timeout)
millisecondsTimeout:等待线程终止的毫秒数。
timeout:等待线程终止的时间量的TimeSpan。
线程的优先级指定一个线程相对于另一个线程的相对优先级。每个线程都有一个分配的优先级。在公共语言运行库内创建的线程最初被分配为Normal优先级,而在公共语言运行库外创建的线程,在进入公共语言运行库时将保留其先前的优先级。
优先级值 | 说明 |
---|---|
AboveNormal | 可以将Thread安排在具有Highest优先级的线程之后,在具有Normal优先级的线程之前 |
BelowNormal | 可以将Thread安排在具有Normal优先级的线程之后,在具有Lowest优先级的线程之前 |
Highest | 可以将Thread安排在具有任何其他优先级的线程之前 |
Lowest | 可以将Thread安排在具有任何其他优先级的线程之后 |
Normal | 可以将Thread安排在具有AboveNormal优先级的线程之后 ,在具有BelowNormal优先级的线程之前。默认情况下,线程具有Normal优先级 |
线程同步可以分别使用C#中的lock关键字、Monitor类、Interlocked类和Mutex类实现。
(1)lock关键字可以用来确保代码块完成运行,而不会被其他线程中断,它是通过在代码块运行期间为给定对象获取互斥锁来实现的。
样例:
using System.Text;
using System.Threading;
namespace Alei
{
class Program
{
static void Main(string[] args)
{
Program myProgram = new Program(); //实例化类对象
myProgram.LockThread(); //调用锁定线程方法
}
void LockThread()
{
lock(this) //锁定当前线程,以实现同步
{
Console.WriteLine("锁定线程以实现线程同步");
}
}
}
}
(2)Monitor类提供了同步对象的访问机制,它通过向单个线程授予对象锁来控制对象的访问,对象锁提供限制访问代码块(通常称为临界区)的能力。
样例:
using System.Text;
using System.Threading;
namespace Alei
{
class Program
{
static void Main(string[] args)
{
Program myProgram = new Program(); //实例化类对象
myProgram.LockThread(); //调用锁定线程方法
}
void LockThread()
{
Monitor.Enter(this) //锁定当前线程
Console.WriteLine("锁定线程以实现线程同步");
Monitor.Exit(this); //释放当前线程
}
}
}
(3)当两个或更多线程需要同时访问一个共享资源时,系统需要使用同步机制来确保一次只有一个线程使用该资源。Mutex类是同步基元,它只向一个线程授予对共享资源的独占访问权。如果一个线程获取了互斥体,则要获取该互斥体的第二个线程将被挂起,直到第一个线程释放该互斥体。
样例:
using System.Text;
using System.Threading;
namespace Alei
{
class Program
{
static void Main(string[] args)
{
Program myProgram = new Program(); //实例化类对象
myProgram.LockThread(); //调用锁定线程方法
}
void LockThread()
{
Mutex myMutex = new Mutex(false); //实例化Mutex类对象
myMutex.WaitOne(); //阻止当前线程
Console.WriteLine("锁定线程以实现线程同步");
myMutex.ReleaseMutex(); //释放Mutex对象
}
}
}