zoukankan      html  css  js  c++  java
  • .NET多线程

    参考:

    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);
    View Code

    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);
                }
            }
    View Code

    设置最大最小工作者线程,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("------------------------------------");
            }
        }
    View Code

    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;
                }
            }
        }
    }
    View Code

    示例 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));
            }
  • 相关阅读:
    字符串替换
    字符串查找
    字符串比较
    字节与字符串相互转换
    1365. How Many Numbers Are Smaller Than the Current Number
    1486. XOR Operation in an Array
    1431. Kids With the Greatest Number of Candies
    1470. Shuffle the Array
    1480. Running Sum of 1d Array
    【STM32H7教程】第56章 STM32H7的DMA2D应用之刷色块,位图和Alpha混合
  • 原文地址:https://www.cnblogs.com/caolingyi/p/8534432.html
Copyright © 2011-2022 走看看