.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));
        }
原文地址:https://www.cnblogs.com/caolingyi/p/8534432.html