C#的多线程处理
2008-11-19 00:43
176 查看
一、线程简介
通常C# 程序具有一个线程。这个线程从 Main方法的执行开始启动到Main方法的执行结束时线程终止。Main 直接或间接执行的每一个命令都由默认线程(或主线程)执行,当
Main 返回时此线程也将终止。不过,可以创建辅助线程,以便与主线程一起并行执行代码。这些线程通常称为“辅助线程”。
辅助线程可以用于执行耗时较多的任务或时间要求紧迫的任务,而不必占用主线程。例如,辅助线程经常用在服务器应用程序中,以便无需等待前面的请求完
成即可响应传入的请求。辅助线程还可用于在桌面应用程序中执行“后台”任务,以便使主线程(用于驱动用户界面元素)保持对用户操作的响应。
多线程处理解决了吞吐量和响应性的问题,但同时也带来了资源共享问题,如死锁和争用状态。多线程特别适用于需要不同资源(如文件句柄和网络连接)的任务。为单个资源分配多个线程可能会导致同步问题,线程会被频繁阻止以等待其他线程,从而与使用多线程的初衷背道而驰。
常见的策略是使用辅助线程执行不需要大量占用其他线程所使用的资源的、耗时较多的任务或时间要求紧迫的任务。实际上,程序中的某些资源必须由多个线程访问。考虑到这些情况,System.Threading 命名空间提供了用于同步线程的类。这些类包括 Mutex、Monitor、Interlocked、AutoResetEvent
和 ManualResetEvent。
您可以使用这些类中的部分或所有类来同步多个线程的活动,但是某些多线程处理支持由 C# 语言提供。例如,C# 中的
Lock 语句通过隐式使用 Monitor 来提供同步功能。
二、线程的生命周期
三、与线程有关的类
与C#有关的类都在System.Threading命名空间中, System.Threading 命名空间提供一些使得可以进行多线程编程的类和接口。除同步线程活动和访问数据的类(Mutex、Monitor、Interlocked、AutoResetEvent 等)外,此命名空间还包含一个 ThreadPool 类(它允许用户使用系统提供的线程池)和一个 Timer 类(它在线程池线程上执行回调方法)。
1. Thread: 创建并控制线程,设置其优先级并获取其状态。其中最常用的几个方法如下:
Sleep():将当前线程阻塞指定的毫秒数。
Abort():在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。调用此方法通常会终止线程。
Join():阻塞调用线程,直到某个线程终止时为止。
Start():使线程得以按计划执行。
注意Suspend()为挂起线程和Resume()为继续挂起的线程,这两个方法存在风险,所以不建议使用。具体请参照MS的相关文档
Thread类的常用属性如下:
CurrentThread: 获取当前正在运行的线程。
IsAlive: 获取一个值,该值指示当前线程的执行状态。
Name: 获取或设置线程的名称
Priority:获取或设置一个值,该值指示线程的调度优先级。
ThreadState:获取一个值,该值包含当前线程的状态。
2. ThreadPool:提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。BindHandle:将操作系统句柄绑定到 ThreadPool。
GetAvailableThreads:检索由 GetMaxThreads
方法返回的最大线程池线程数和当前活动线程数之间的差值。
GetMaxThreads:
检索可以同时处于活动状态的线程池请求的数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用
GetMinThreads:
检索线程池在新请求预测中维护的空闲线程数。
QueneUserWorkItem: 将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。
RegisterWaitForSingleObject:
注册正在等待 WaitHandle
的委托。
UnsafeQueueUserWorkItem:
注册一个等待 WaitHandle
的委托。
SetMaxThreads:
设置可以同时处于活动状态的线程池的请求数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
四、示例及其说明
using System;
using System.Threading;
public class Worker
{
// 在线程启动时此方法将被调用
public void DoWork()
{
while (!_shouldStop) // 如果线程正在运行则打印信息
{
Console.WriteLine("worker thread: working...");
}
Console.WriteLine("worker
thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Volatile这个关键字用来提醒编译器这个数据成员将被多线程访问
private volatile bool _shouldStop; // 应该停止
}
public class Program
{
static void Main()
{
// 创建一个线程对象. 这里并不是线程的开始
Worker workerObject = new Worker();
// 这里定义一个新的线程,注意这里没有使用ThreadStart委托
// 另外构造函数接受的是对象的方法的名称
Thread workerThread = new Thread(workerObject.DoWork);
// 这里才是线程的真正开始
workerThread.Start();
Console.WriteLine("主线程: worker线程开始...");
// 循环直到线程被激活,Thread的IsAlive这个属性表示线程是否为活动的
while (!workerThread.IsAlive);
// 将主线程暂停1毫秒,以允许worker这个线程完成自己的工作
Thread.Sleep(1);
// 需要worker这个线程自动停止
workerObject.RequestStop();
// 使用Join这个方法来阻塞当前线程,直到对象的线程终止 workerThread.Join();
Console.WriteLine("main
thread: Worker thread has terminated.");
}
}
通常C# 程序具有一个线程。这个线程从 Main方法的执行开始启动到Main方法的执行结束时线程终止。Main 直接或间接执行的每一个命令都由默认线程(或主线程)执行,当
Main 返回时此线程也将终止。不过,可以创建辅助线程,以便与主线程一起并行执行代码。这些线程通常称为“辅助线程”。
辅助线程可以用于执行耗时较多的任务或时间要求紧迫的任务,而不必占用主线程。例如,辅助线程经常用在服务器应用程序中,以便无需等待前面的请求完
成即可响应传入的请求。辅助线程还可用于在桌面应用程序中执行“后台”任务,以便使主线程(用于驱动用户界面元素)保持对用户操作的响应。
多线程处理解决了吞吐量和响应性的问题,但同时也带来了资源共享问题,如死锁和争用状态。多线程特别适用于需要不同资源(如文件句柄和网络连接)的任务。为单个资源分配多个线程可能会导致同步问题,线程会被频繁阻止以等待其他线程,从而与使用多线程的初衷背道而驰。
常见的策略是使用辅助线程执行不需要大量占用其他线程所使用的资源的、耗时较多的任务或时间要求紧迫的任务。实际上,程序中的某些资源必须由多个线程访问。考虑到这些情况,System.Threading 命名空间提供了用于同步线程的类。这些类包括 Mutex、Monitor、Interlocked、AutoResetEvent
和 ManualResetEvent。
您可以使用这些类中的部分或所有类来同步多个线程的活动,但是某些多线程处理支持由 C# 语言提供。例如,C# 中的
Lock 语句通过隐式使用 Monitor 来提供同步功能。
二、线程的生命周期
三、与线程有关的类
与C#有关的类都在System.Threading命名空间中, System.Threading 命名空间提供一些使得可以进行多线程编程的类和接口。除同步线程活动和访问数据的类(Mutex、Monitor、Interlocked、AutoResetEvent 等)外,此命名空间还包含一个 ThreadPool 类(它允许用户使用系统提供的线程池)和一个 Timer 类(它在线程池线程上执行回调方法)。
1. Thread: 创建并控制线程,设置其优先级并获取其状态。其中最常用的几个方法如下:
Sleep():将当前线程阻塞指定的毫秒数。
Abort():在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。调用此方法通常会终止线程。
Join():阻塞调用线程,直到某个线程终止时为止。
Start():使线程得以按计划执行。
注意Suspend()为挂起线程和Resume()为继续挂起的线程,这两个方法存在风险,所以不建议使用。具体请参照MS的相关文档
Thread类的常用属性如下:
CurrentThread: 获取当前正在运行的线程。
IsAlive: 获取一个值,该值指示当前线程的执行状态。
Name: 获取或设置线程的名称
Priority:获取或设置一个值,该值指示线程的调度优先级。
ThreadState:获取一个值,该值包含当前线程的状态。
2. ThreadPool:提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。BindHandle:将操作系统句柄绑定到 ThreadPool。
GetAvailableThreads:检索由 GetMaxThreads
方法返回的最大线程池线程数和当前活动线程数之间的差值。
GetMaxThreads:
检索可以同时处于活动状态的线程池请求的数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用
GetMinThreads:
检索线程池在新请求预测中维护的空闲线程数。
QueneUserWorkItem: 将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。
RegisterWaitForSingleObject:
注册正在等待 WaitHandle
的委托。
UnsafeQueueUserWorkItem:
注册一个等待 WaitHandle
的委托。
SetMaxThreads:
设置可以同时处于活动状态的线程池的请求数目。所有大于此数目的请求将保持排队状态,直到线程池线程变为可用。
四、示例及其说明
using System;
using System.Threading;
public class Worker
{
// 在线程启动时此方法将被调用
public void DoWork()
{
while (!_shouldStop) // 如果线程正在运行则打印信息
{
Console.WriteLine("worker thread: working...");
}
Console.WriteLine("worker
thread: terminating gracefully.");
}
public void RequestStop()
{
_shouldStop = true;
}
// Volatile这个关键字用来提醒编译器这个数据成员将被多线程访问
private volatile bool _shouldStop; // 应该停止
}
public class Program
{
static void Main()
{
// 创建一个线程对象. 这里并不是线程的开始
Worker workerObject = new Worker();
// 这里定义一个新的线程,注意这里没有使用ThreadStart委托
// 另外构造函数接受的是对象的方法的名称
Thread workerThread = new Thread(workerObject.DoWork);
// 这里才是线程的真正开始
workerThread.Start();
Console.WriteLine("主线程: worker线程开始...");
// 循环直到线程被激活,Thread的IsAlive这个属性表示线程是否为活动的
while (!workerThread.IsAlive);
// 将主线程暂停1毫秒,以允许worker这个线程完成自己的工作
Thread.Sleep(1);
// 需要worker这个线程自动停止
workerObject.RequestStop();
// 使用Join这个方法来阻塞当前线程,直到对象的线程终止 workerThread.Join();
Console.WriteLine("main
thread: Worker thread has terminated.");
}
}
相关文章推荐
- C# 多线程并发处理数据库数据,发送信号等待处理完统一插入
- c#(asp.net) 多线程示例,用于同时处理多个任务
- 用最简单的方式在C#中使用多线程加速耗时的图像处理算法的执行(多核机器)。
- 用最简单的方式在C#中使用多线程加速耗时的图像处理算法的执行(多核机器)。
- C# 多线程问题处理小结
- C#中的多线程超时处理实践
- C# 为啥用invoke,实际上是处理多线程的问题
- c# 关于Task类处理多线程的学习
- C# 多线程处理相关说明: WaitHandle,waitCallback, ThreadPool.QueueUserWorkItem
- C#在处理多线程更新到UI控件的多种方法
- <转载>C#与.NET对多线程的处理
- c#(asp.net) 多线程示例,用于同时处理多个任务
- C#制作多线程处理强化版网络爬虫
- C#与.NET对多线程的处理(转)
- C#中的多线程超时处理实践方案
- C# 多线程,解决处理大数据时窗体(不能拖动等)假死现象
- C#(asp.net)多线程用法示例(可用于同时处理多个任务)
- C# 多线程并发处理数据库数据,发送信号等待处理完统一插入.
- C#使用_多线程处理
- C# 多线程控件处理