C# - 多线程 之 Process与Thread与ThreadPool
Process
进程类
// 提供对本地和远程进程的访问,启动/停止本地系统进程 public class Process : Component { public int Id { get; } // 系统生成的进程唯一标识符 public string ProcessName { get; } // 进程名称 public string MachineName { get; } // 运行进程的计算机名称 public ProcessThreadCollection Threads { get; } // 进程关联的线程集合(System.Diagnostics.ProcessThread类型的数组) public ProcessModule MainModule { get; } // 进程主模块 public ProcessModuleCollection Modules { get; } // 进程加载的模块集合(System.Diagnostics.ProcessModule类型的数组) public DateTime StartTime { get; } // 进程启动时间 public DateTime ExitTime { get; } // 进程退出时间 public int ExitCode { get; } // 进程终止时指定的代码值 public bool HasExited { get; } // 进程是否已终止 public TimeSpan TotalProcessorTime { get; } // 进程的总的处理器时间 public TimeSpan UserProcessorTime { get; } // 进程的用户处理器时间 public TimeSpan PrivilegedProcessorTime { get; } // 进程的特权处理器时间 public ProcessPriorityClass PriorityClass { get; set; } // 进程的总体优先级别类别 public int BasePriority { get; } // 进程的基本优先级别,由PriorityClass计算 public IntPtr Handle { get; } // 进程的本机句柄(进程启动时OS为进程分配的句柄,用来跟踪进程属性) public int HandleCount { get; } // 进程打开的操作系统句柄数 public int WorkingSet { get; } // 进程当前使用的物理内存总量 public int PrivateMemorySize { get; } // 为进程分配的专用内存字节数 public int VirtualMemorySize { get; } // 进程的虚拟内存大小 public bool Responding { get; } // 进程的用户界面当前是否响应系统 public int SessionId { get; } // 进程的终端服务会话标识符 public Process(); // System.IO.StreamReader/StreamWriter public StreamReader StandardError { get; } // 用于读取应用程序的标准错误流 public StreamWriter StandardInput { get; } // 用于写入应用程序的标准输入流 public StreamReader StandardOutput { get; } // 用于读取应用程序的标准输出流 public bool Start([string fileName]); // 启动进程 public bool Start(ProcessStartInfo startInfo); public void Kill(); // 停止进程 public void Close(); // 关闭进程,释放与此组件关联的所有资源 public void Refresh(); // 放弃进程的、已缓存到该进程组件内的任何信息 protected override void Dispose(bool disposing); // 释放进程使用的所有资源 public bool WaitForExit([int milliseconds]); // 等待进程退出 // 获取新的System.Diagnostics.Process组件并与当前活动的进程关联 public static Process GetCurrentProcess(); // 获取[指定计算机上]运行的所有进程资源 public static Process[] GetProcesses([string machineName]); // 获取[指定计算机上]由ProcessID对应的进程 public static Process GetProcessById(int processId [, string machineName]); // 获取[指定计算机上]由ProcessName对应的进程 public static Process[] GetProcessesByName(string processName [, string machineName]); }
进程优先级
// 指示进程优先级 public enum ProcessPriorityClass { Idle = 64, // 指定进程的线程只能在系统空闲时运行 BelowNormal = 16384, Normal = 32, // 指定进程没有特殊的安排需求 AboveNormal = 32768, High = 128, // 指定进程执行必须立即执行的时间关键任务 RealTime = 256, // 可能的最高优先级 }
进程优先级与进程的每个线程的优先级值一起确定其每个线程的基本优先级别。
其他进程相关
// 进程路径信息 string startup-Path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; 或 System.Reflection.Assembly.GetExecutingAssembly().Location; // 进程目录信息 string startup-Directory = System.IO.Path.GetDirectoryName(startupPath); 或 System.IO.Directory.GetCurrentDirectory(); 或 System.Environment.CurrentDirectory; 或 System.Windows.Forms.Application.StartupPath;
Thread
线程类,.NET中的CLR线程可看作是对操作系统线程的封装,CLR线程与操作系统线程对应,Thread类的实例在调用start()方法后,CLR才会创建一个操作系统线程与之绑定。CLR线程池限制线程的创建速度不超过2个/秒。
属性方法
// 创建并控制线程,设置其优先级并获取其状态 public sealed class Thread : CriticalFinalizerObject, _Thread { public int ManagedThreadId { get; } // 托管线程的唯一标识符 public string Name { get; set; } public bool IsAlive { get; } // 当前线程的执行状态(true:线程已启动且尚未正常终止或中止) public bool IsBackground { get; set; } public bool IsThreadPoolThread { get; } public static Thread CurrentThread { get; } // 获取当前正在运行的线程 public static Context CurrentContext { get; } // 获取当前线程的上下文 public ExecutionContext ExecutionContext { get; } // 管理当前线程的上下文 public ApartmentState ApartmentState { get; set; } // 线程的单元状态 public ThreadPriority Priority { get; set; } public ThreadState ThreadState { get; } // 指定线程启动时要调用的委托方法,(指定线程的最大堆栈大小) public Thread(ParameterizedThreadStart start [, int maxStackSize]); public Thread(ThreadStart start [, int maxStackSize]); public override int GetHashCode(); // 当前线程的哈希代码 public static int GetDomainID(); // 唯一的应用程序域标识符 public static AppDomain GetDomain(); // 当前线程正在其中运行的当前应用程序域 public ApartmentState GetApartmentState(); public void SetApartmentState(ApartmentState state); // 启动前设置线程的单元状态 public bool TrySetApartmentState(ApartmentState state); public void Start([object parameter]); // 启动线程(->Running) public void Suspend(); // 挂起线程 public void Resume(); // 继续已挂起的线程 public void Interrupt(); // 中断处于WaitSleepJoin状态的线程 public void Join(); // 阻塞调用线程,直到某个线程终止为止 public void Abort([object stateInfo]); // 终止线程(引发ThreadAbortException、开始终止线程的过程) public static void ResetAbort(); // 取消为当前线程请求的Abort(System.Object) public static void Sleep(); // 阻塞线程 public static void SpinWait(int iterations); // 线程等待(iterations定义等待时间) public static bool Yield(); // true:操作系统选择并转而执行另一个线程 public static LocalDataStoreSlot AllocateNamedDataSlot(string name); public static LocalDataStoreSlot GetNamedDataSlot(string name); public static void FreeNamedDataSlot([string name]); public static object GetData(LocalDataStoreSlot slot); public static void SetData(LocalDataStoreSlot slot, object data); public static Type VolatileRead(ref Type address); // 读取字段值 public static void VolatileWrite(ref Type address, Type value); // 字段赋值 }
其中,ThreadStart和ParameterizedThreadStart定义委托,均表示在System.Threading.Thread上要执行的方法:
public delegate void ThreadStart(); public delegate void ParameterizedThreadStart(object obj);
其中,ApartmentState指定System.Threading.Thread的单元状态
public enum ApartmentState { STA = 0, // System.Threading.Thread将创建并进入一个单线程单元 MTA = 1, // System.Threading.Thread将创建并进入一个多线程单元 Unknown = 2, // 单元状态未指定 }
线程调度优先级
public enum ThreadPriority { Lowest = 0, BelowNormal = 1, Normal = 2, // 默认优先级 AboveNormal = 3, Highest = 4, }
线程生命周期
线程执行状态
public enum ThreadState { Running = 0, // 线程已启动,它未被阻塞且没有挂起的System.Threading.ThreadAbortException StopRequested = 1, // 正在请求线程停止(仅用于内部) SuspendRequested = 2, // 正在请求线程挂起 Background = 4, // 线程正作为后台线程执行 Unstarted = 8, // 尚未对线程调用Start()方法、线程未启动 Stopped = 16, // 线程已停止 WaitSleepJoin = 32, // 线程已被阻止 Suspended = 64, // 线程已挂起 AbortRequested = 128, // 已对线程调用Abort(System.Object)方法,但线程尚未收到System.Threading.ThreadAbortException试图终止它的挂起 Aborted = 256, // 线程状态包括AbortRequested且该线程已死,但其状态尚未更改为Stopped }
其中,ThreadState.WaitSleepJoin状态的可能原因:
- 调用Sleep(System.Int32)方法或Join()方法;
- 请求锁定:调用Monitor.Enter(System.Object)方法或Monitor.Wait(System.Object,System.Int32,System.Boolean)方法;
- 等待线程同步对象:ManualResetEvent或AutoResetEvent;
多线程读写变量
private int ConnectionCount = 0; //当前连接数 Interlocked.Decrement(ref ConnectionCount); Interlocked.Increment(ref ConnectionCount); Thread.VolatileRead(ref ConnectionCount)
ThreadPool
线程池,由系统维护的容纳线程的容器,一个应用程序最多只能有一个线程池。ThreadPool适于并发运行若干个运行时间不长且互不干扰的函数,通过复用有限个固定线程为大量操作服务,减少创建和销毁线程的代价、提高效率。托管线程池中的线程默认为后台线程,即线程的IsBackground属性为true,意味着所有前台线程退出后,ThreadPool线程不会让应用程序保持运行。
- 不能控制线程池中线程的开始、挂起、和中止;
- 不适应于执行时间比较长的线程;
// 提供一个线程池,该线程池可用于发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器 public static class ThreadPool{ // 将工作函数排入线程池(,同时指定工作函数需要的参数) // 每排入一个工作函数,相当于请求创建一个线程,当线程池中有线程可用时、执行工作函数 public static bool QueueUserWorkItem(WaitCallback callBack); public static bool QueueUserWorkItem(WaitCallback callBack, object state); // 设置线程池维护的最小空闲线程数 public static bool SetMinThreads(int workerThreads, int completionPortThreads); // 设置线程池中可同时处于活动状态的线程数目,大于此数目的请求将保持排队状态,直到有线程变为可用 public static bool SetMaxThreads(int workerThreads, int completionPortThreads); // 检索当前线程池维护的空闲线程的最小数目 public static void GetMinThreads(out int workerThreads, out int completionPortThreads); // 检索当前线程池维护可同时处于活动状态的的线程的最大数目 public static void GetMaxThreads(out int workerThreads, out int completionPortThreads); // 获取当前可用的线程数(= GetMaxThreads - 当前线程池中活动的线程数) public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads); }
其中,WaitCallback表示线程池线程要执行的回调方法:
public delegate void WaitCallback(object state);
以工作中QC框架中的一段代码示例:
其他线程池
ManagedThreadPool
由Stephen Toub完全用C#托管代码实现的线程池,quite excellent pool,
SmartThreadPool
智能线程池,开源线程池组件,用SmartThreadPool可以简单实现支持多线程的程序,线程池来管理线程、可以减少死锁的出现,同时支持简单的生产者-消费者模式。
- 下载SmartThreadPool:http://smartthreadpool.codeplex.com/
- 引用SmartThreadPool.dll
参考
问题总结
[1].请求并发量大时,服务器异步创建线程处理请求响应慢问题
ThreadPool.SetMinThreads(300, 300)
建议:使用C#线程池时,一定要先设置SetMinThreads,再设置SetMaxThreads。其他参考 ,其他参考
[2].请