参考:
https://www.cnblogs.com/edisonchou/p/4848131.html
https://www.cnblogs.com/willick/p/4177977.html#header03
1、线程 System.Threading.Thread类
Console.WriteLine("开始测试线程1"); // 初始化一个线程 thread1 Thread thread1 = new Thread(Work1); // 这时状态:UnStarted PrintState(thread1); // 启动线程 Console.WriteLine("现在启动线程"); thread1.Start(); // 这时状态:Running PrintState(thread1); // 让线程飞一会 3s Thread.Sleep(3 * 1000); // 让线程挂起 Console.WriteLine("现在挂起线程"); thread1.Suspend(); // 给线程足够的时间来挂起,否则状态可能是SuspendRequested Thread.Sleep(1000); // 这时状态:Suspend PrintState(thread1); // 继续线程 Console.WriteLine("现在继续线程"); thread1.Resume(); // 这时状态:Running PrintState(thread1); // 停止线程 Console.WriteLine("现在停止线程"); thread1.Abort(); // 给线程足够的时间来终止,否则的话可能是AbortRequested Thread.Sleep(1000); // 这时状态:Stopped PrintState(thread1);
2、线程池 System.Threading.ThreadPool 类
static void Main(string[] args) { string taskInfo = "运行10秒"; // 插入一个新的请求到线程池 bool result = ThreadPool.QueueUserWorkItem(DoWork, taskInfo); // 分配线程有可能会失败 if (!result) { Console.WriteLine("分配线程失败"); } else { Console.WriteLine("按回车键结束程序"); } Console.ReadKey(); } private static void DoWork(object state) { // 模拟做了一些操作,耗时10s for (int i = 0; i < 10; i++) { Console.WriteLine("工作者线程的任务是:{0}", state); Thread.Sleep(1000); } }
设置最大最小工作者线程,IO线程的数量
class Program { static void Main(string[] args) { // 打印阈值和可用数量 GetLimitation(); GetAvailable(); // 使用掉其中三个线程 Console.WriteLine("此处申请使用3个线程..."); ThreadPool.QueueUserWorkItem(Work); ThreadPool.QueueUserWorkItem(Work); ThreadPool.QueueUserWorkItem(Work); Thread.Sleep(1000); // 打印阈值和可用数量 GetLimitation(); GetAvailable(); // 设置最小值 Console.WriteLine("此处修改了线程池的最小线程数量"); ThreadPool.SetMinThreads(10, 10); // 打印阈值 GetLimitation(); Console.ReadKey(); } // 运行10s的方法 private static void Work(object o) { Thread.Sleep(10 * 1000); } // 打印线程池的上下限阈值 private static void GetLimitation() { int maxWork, minWork, maxIO, minIO; // 得到阈值上限 ThreadPool.GetMaxThreads(out maxWork, out maxIO); // 得到阈值下限 ThreadPool.GetMinThreads(out minWork, out minIO); // 打印阈值上限 Console.WriteLine("线程池最多有{0}个工作者线程,{1}个IO线程", maxWork.ToString(), maxIO.ToString()); // 打印阈值下限 Console.WriteLine("线程池最少有{0}个工作者线程,{1}个IO线程", minWork.ToString(), minIO.ToString()); Console.WriteLine("------------------------------------"); } // 打印可用线程数量 private static void GetAvailable() { int remainWork, remainIO; // 得到当前可用线程数量 ThreadPool.GetAvailableThreads(out remainWork, out remainIO); // 打印可用线程数量 Console.WriteLine("线程池中当前有{0}个工作者线程可用,{1}个IO线程可用", remainWork.ToString(), remainIO.ToString()); Console.WriteLine("------------------------------------"); } }
3、并发异步
class Program { static void Main(string[] args) { Thread t1 = new Thread(Working); t1.Name = "Thread1"; Thread t2 = new Thread(Working); t2.Name = "Thread2"; Thread t3 = new Thread(Working); t3.Name = "Thread3"; // 依次启动3个线程。 t1.Start(); t2.Start(); t3.Start(); Console.ReadKey(); } // 每个线程都同时在工作 static void Working() { // 模拟1000次写日志操作 for (int i = 0; i < 1000; i++) { // 异步写文件 Logger.Write(Thread.CurrentThread.Name + " writes a log: " + i + ", on " + DateTime.Now.ToString() + ". "); }// 做一些其它的事件 for (int i = 0; i < 1000; i++) { } } }
4、并发控制 锁
class Program { static bool done; static object locker = new object(); // !! static void Main(string[] args) { new Thread(Go).Start(); // 在新的线程上调用Go Go(); // 在主线程上调用Go Console.ReadKey(); } static void Go() { lock (locker) { if (!done) { Thread.Sleep(500); // Doing something. Console.WriteLine("Done"); done = true; } } } }
示例 Logger类
调用 write(content)方法,Task.Run (.net 4.5)
// 用于存放写日志任务的队列 private Queue<Action> _queue; // 用于写日志的线程 private Thread _loggingThread; // 用于通知是否有新日志要写的“信号器” private ManualResetEvent _hasNew; // 构造函数,初始化。 private Logger() { _queue = new Queue<Action>(); _hasNew = new ManualResetEvent(false); _loggingThread = new Thread(Process); _loggingThread.IsBackground = true; _loggingThread.Start(); } // 使用单例模式,保持一个Logger对象 private static readonly Logger _logger = new Logger(); private static Logger GetInstance() { /* 不安全代码 lock (locker) { if (_logger == null) { _logger = new Logger(); } }*/ return _logger; } // 处理队列中的任务 private void Process() { while (true) { // 等待接收信号,阻塞线程。 _hasNew.WaitOne(); // 接收到信号后,重置“信号器”,信号关闭。 _hasNew.Reset(); // 由于队列中的任务可能在极速地增加,这里等待是为了一次能处理更多的任务,减少对队列的频繁“进出”操作。 Thread.Sleep(100); // 开始执行队列中的任务。 // 由于执行过程中还可能会有新的任务,所以不能直接对原来的 _queue 进行操作, // 先将_queue中的任务复制一份后将其清空,然后对这份拷贝进行操作。 Queue<Action> queueCopy; lock (_queue) { queueCopy = new Queue<Action>(_queue); _queue.Clear(); } foreach (var action in queueCopy) { action(); } } } private void WriteLog(string content) { lock (_queue) { // 将任务加到队列 _queue.Enqueue(() => File.AppendAllText("log.txt", content)); } // 打开“信号” _hasNew.Set(); } // 公开一个Write方法供外部调用 public static void Write(string content) { // WriteLog 方法只是向队列中添加任务,执行时间极短,所以使用Task.Run。 Task.Run(() => GetInstance().WriteLog(content)); }