threadpool 里的线程可以不退出吗(C多线程)
threadpool 里的线程可以不退出吗(C多线程)Dead 任务完成后,处于死亡或终止状态Not Runable 非运行状态,调用了sleep、wait或I/O被阻塞UnStarted 处于创建但未启动状态Runnable 调用了start,处于可运行或准备运行状态Running 运行中状态
线程和进程进程:进程包含一个程序运行所需要的资源,进程即是一个程序,一个进程可以有多个线程。
线程:操作系统能够进行运算调度的最小单位。

Windows 任务管理器
进程可以有多个线程。
生命周期UnStarted 处于创建但未启动状态
Runnable 调用了start,处于可运行或准备运行状态
Running 运行中状态
Not Runable 非运行状态,调用了sleep、wait或I/O被阻塞
Dead 任务完成后,处于死亡或终止状态
ThreadThread 常用属性
class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("主线程:" Thread.CurrentThread.ManagedThreadId);
            Thread t = new Thread(new ThreadStart(Thread_A));
            Console.WriteLine("创建线程 -- 线程状态:" t.ThreadState);
            t.Start();
            Thread.Sleep(1000); //  睡眠1秒
            Console.ReadKey();
        }
        private static void Thread_A()
        {
            Console.WriteLine("常用属性值:");
            Console.WriteLine("当前运行线程实例:"  Thread.CurrentThread);
            Console.WriteLine("当前线程唯一ID:" Thread.CurrentThread.ManagedThreadId);
            Console.WriteLine("当前线程名称:" Thread.CurrentThread.Name);
            Console.WriteLine("当前线程优先级:" Thread.CurrentThread.Priority);
            Console.WriteLine("当前线程状态:" Thread.CurrentThread.ThreadState);
            Console.WriteLine("当前线程是否处于活跃:" Thread.CurrentThread.IsAlive);
            Console.WriteLine("当前线程是否为后台线程:" Thread.CurrentThread.IsBackground);
           /*
           前台线程:主程序必须等待线程执行完毕后才能退出程序
					 后台线程:主程序执行完毕后就退出,不管线程是否完成
           */
        }
    }
    

输出
Thread 优先级
class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(new ThreadStart(A));
            t1.Start();
            Thread t2 = new Thread(new ThreadStart(B));
            t2.Start();
            Thread t3 = new Thread(new ThreadStart(C));
            t3.Start();
            Console.ReadKey();
        }
        private static void A()
        {
            Console.WriteLine("A");
        }
        private static void B()
        {
            Console.WriteLine("B");
        }
        private static void C()
        {
            Console.WriteLine("C");
        }
    }
    
第一次输出:ABC
第二次输出:BAC
第三次输出:ABC
第四次输出:ACB

第四次输出
Thread 优先级相同时没有先后顺序,设置优先级:
class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(new ThreadStart(A));
            t1.Start();
            t1.Priority = ThreadPriority.Highest;
            Thread t2 = new Thread(new ThreadStart(B));
            t2.Start();
            t2.Priority = ThreadPriority.Highest;
            Thread t3 = new Thread(new ThreadStart(C));
            t3.Start();
            t3.Priority = ThreadPriority.Highest;
            Thread t4 = new Thread(new ThreadStart(D));
            t4.Start();
            Console.ReadKey();
        }
        private static void A()
        {
            Console.WriteLine("A");
        }
        private static void B()
        {
            Console.WriteLine("B");
        }
        private static void C()
        {
            Console.WriteLine("C");
        }
        private static void D()
        {
            Console.WriteLine("D");
        }
    }
    
第一次输出:CABD
第二次输出:ABCD
第三次输出:ACBD
第四次输出:ACBD
D的优先级最低,ABC优先级都是 Highest 同优先级不分顺序
带参 Threadclass Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main 标识:" Thread.CurrentThread.ManagedThreadId);
            Thread t1 = new Thread(new ParameterizedThreadStart(A)); // 带参数的方法
            t1.Start("ThreadTest"); // 传参
            Console.WriteLine("Main 标识:" Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
        private static void A(object data)
        {
            Console.WriteLine("Message: " data " 标识:" Thread.CurrentThread.ManagedThreadId);
        }
    }
    

输出
Thread 线程阻塞Thread.Join() 可以阻塞主线程
class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(() => { Console.WriteLine("A"); });
            t1.Start();
            t1.Join();
            Console.WriteLine("主线程");
            Console.Read();
        }
    }
    

输出
阻塞所有线程,t1 执行完成之后再执行其他线程
Thread.Sleep(); 阻塞当前线程
class Program
    {
        static void Main(string[] args)
        {
            Thread t1 = new Thread(() =>
            {
                Console.WriteLine("A");
                Thread.Sleep(1000);
            });
            t1.Start();
            Console.WriteLine("主线程");
            Console.Read();
        }
    }
    

输出
当前线程阻塞1s,Thread.Sleep() 单位是ms
Thread 方法
来源:https://www.lidihuo.com/csharp/csharp-thread-class.html
Lock 线程锁例:A、B同时在银行取钱,余额只有1000,两人都需要取1000,A取出来1000后,B取得时候提示余额不足
class Program
    {
        private static object obj = new object();
        private static int money = 1000;
        static void Main(string[] args)
        {
            Thread thread1 = new Thread(Sum1);
            thread1.Start();
            Thread thread2 = new Thread(Sum1);
            thread2.Start();
            Console.ReadKey();
        }
        public static void Sum1()
        {
            lock (obj)
            {
                if(money >= 1000)
                {
                    money -= 1000;
                    Console.WriteLine("余额:{0}" money);
                }
                else
                {
                    Console.WriteLine("余额不足");
                }
            }
        }
    }
    

输出
ThreadPoolThreadPool 线程池是为了方便对线程进行管理,线程池可以限制线程数量且可以重复使用
static void Main(string[] args)
        {
            Console.WriteLine("Main 标识:" Thread.CurrentThread.ManagedThreadId);
            ThreadPool.QueueUserWorkItem(p => A("")); // A括号里面传参数
            ThreadPool.QueueUserWorkItem(new WaitCallback(A));
            Console.WriteLine("Main 标识:" Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
        private static void A(object data)
        {
            Console.WriteLine("Message: " data " 标识:" Thread.CurrentThread.ManagedThreadId);
        }
    

输出
class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main 标识:" Thread.CurrentThread.ManagedThreadId);
            Thread t1 = new Thread(new ThreadStart(A));
            Thread t2 = new Thread(new ThreadStart(B));
            t1.Start();
            t2.Start();
            Console.WriteLine("Main 标识:" Thread.CurrentThread.ManagedThreadId);
            Console.ReadLine();
        }
        private static void B()
        {
            Console.WriteLine("Thread B");
        }
        private static void A()
        {
            Console.WriteLine("Thread A");
        }
    }
    

输出
两端代码运行过多次,Thread 主线程会等待线程,ThreadPool 主线程不会等待线程
ThreadPool 线程重用、线程数量线程数量
class Program
{
  static void Main(string[] args)
  {
  int workerThreads; // 工作线程
  int completionPortThreads; // I/O 线程
  ThreadPool.GetMaxThreads(out workerThreads  out completionPortThreads);
  Console.WriteLine($"最大线程数:{workerThreads} {completionPortThreads}");
  ThreadPool.GetMinThreads(out workerThreads  out completionPortThreads);
  Console.WriteLine($"最小线程数:{workerThreads} {completionPortThreads}");
  Console.ReadLine();
  }
}
    

输出
设置数量
class Program
    {
        static void Main(string[] args)
        {
            int workerThreads; // 工作线程
            int completionPortThreads; // I/O 线程
            // 设置最大线程
            ThreadPool.SetMaxThreads(5  5);
            // 设置最小线程
            ThreadPool.SetMinThreads(1  1);
            ThreadPool.GetMaxThreads(out workerThreads  out completionPortThreads);
            Console.WriteLine($"最大线程数:{workerThreads} {completionPortThreads}");
            ThreadPool.GetMinThreads(out workerThreads  out completionPortThreads);
            Console.WriteLine($"最小线程数:{workerThreads} {completionPortThreads}");
            Console.ReadLine();
        }
    }
    

输出
线程重用
class Program
    {
        static void Main(string[] args)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetMoney));
            Console.ReadKey();
        }
        private static void GetMoney(object state)
        {
            Console.WriteLine("线程标识: " Thread.CurrentThread.ManagedThreadId);
        }
    }
    

输出
从输出的线程标识中可以看出只用了三个线程,减少了线程的创建
带参 ThreadPoolclass Program
    {
        static void Main(string[] args)
        {
            string msg = "The User Does't exit";
            object mg = "Hello Banananana";
            ThreadPool.QueueUserWorkItem((a) => Message(msg));
            ThreadPool.QueueUserWorkItem(new WaitCallback(Message)  mg); // 传参类型需要 Object
            Console.Read();
        }
        private static void Message(string msg)
        {
            Console.WriteLine(msg);
        }
        private static void Message(object msg)
        {
            Console.WriteLine(msg "");
        }
    }
    

输出

QueueUserWorkItem

回调方法
TaskThreadPool 不能控制线程执行的顺序,也不能获取线程池内线程的取消、异常、完成的通知
Task 无返回值线程class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始执行");
            var factory = new TaskFactory();
            Task t1 = factory.StartNew(() => Console.WriteLine("A,标识: {0}" Thread.CurrentThread.ManagedThreadId));
            Task t2 = Task.Factory.StartNew(() => Console.WriteLine("B,标识: {0}" Thread.CurrentThread.ManagedThreadId));
            Task t3 = new Task(() => Console.WriteLine("C,标识: {0}" Thread.CurrentThread.ManagedThreadId));
            t3.Start();
            Task t4 = Task.Run(() => Console.WriteLine("D,标识: {0}" Thread.CurrentThread.ManagedThreadId));
            Console.Read();
        }
    }
    

输出
Task 有返回值线程class Program
    {
        static void Main(string[] args)
        {
            Task<string> t1 = new Task<string>(() => { return $"A  标识:{Thread.CurrentThread.ManagedThreadId}"; });
            t1.Start();
            Task<string> t2 = Task.Factory.StartNew(() => { return $"B  标识:{Thread.CurrentThread.ManagedThreadId}"; });
            Task<string> t3 = Task.Run(() => { return $"C  标识:{Thread.CurrentThread.ManagedThreadId}"; });
            Console.WriteLine(t1.Result);
            Console.WriteLine(t2.Result);
            Console.WriteLine(t3.Result);
            Console.Read();
        }
    }
    

输出
注:Task.Result 返回结果时会阻塞线程
Task 同步执行class Program
    {
        static void Main(string[] args)
        {
            Task t1 = new Task(() => Console.WriteLine("Task 线程"));
            t1.RunSynchronously(); // 同步方法
            Console.WriteLine("主线程");
            Console.Read();
        }
    }
    

输出
Task 线程阻塞Thread 也有方法可以进行阻塞,但每次只能对一个线程进行阻塞,Task 可以有方法可以解决这个问题,task.Wait() 等待 task 执行完成,类似 Thread.Join(),Task.WaitAll() 执行完所有 task 再解除线程,Task.WaitAny() 只要有一个 task 执行完成就解除线程
Task.Wait
class Program
    {
        static void Main(string[] args)
        {
            Task t1 = new Task(() => { Console.WriteLine("A"); });
            t1.Start();
            t1.Wait();
            Console.WriteLine("主线程");
            Console.Read();
        }
    }
    

Task.Wait()
阻塞所有线程,等待当前执行完成
Task.WaitAll
class Program
    {
        static void Main(string[] args)
        {
            List<Task> list = new List<Task>();
            Task t1 = Task.Run(() => Console.WriteLine("A"));
            Task t2 = Task.Run(() => Console.WriteLine("B"));
            Task t3 = Task.Run(() => Console.WriteLine("C"));
            Task t4 = Task.Run(() => Console.WriteLine("D"));
            list.Add(t1);
            list.Add(t2);
            list.Add(t3);
            list.Add(t4);
            Task.WaitAll(list.ToArray());
            Console.WriteLine("主线程");
            Console.Read();
        }
    }
    

Task.WaitAll
等待 Task线程组 完成
Task.WaitAny
class Program
    {
        static void Main(string[] args)
        {
            List<Task> list = new List<Task>();
            Task t1 = Task.Run(() => Console.WriteLine("A"));
            Task t2 = Task.Run(() => Console.WriteLine("B"));
            Task t3 = Task.Run(() => Console.WriteLine("C"));
            Task t4 = Task.Run(() => Console.WriteLine("D"));
            list.Add(t1);
            list.Add(t2);
            list.Add(t3);
            list.Add(t4);
            Task.WaitAny(list.ToArray());
            Console.WriteLine("主线程");
            Console.Read();
        }
    }
    

Task.WaitAny
线程组任意线程完成就接触阻塞
Task 延续操作有一个需求,需要在 task 线程组 执行完成之后执行
class Program
    {
        static void Main(string[] args)
        {
            List<Task> list = new List<Task>();
            Task t1 = Task.Run(() => Console.WriteLine("A"));
            Task t2 = Task.Run(() => Console.WriteLine("B"));
            Task t3 = Task.Run(() => Console.WriteLine("C"));
            Task t4 = Task.Run(() => Console.WriteLine("D"));
            list.Add(t1);
            list.Add(t2);
            list.Add(t3);
            list.Add(t4);
           // 二选一即可
            Task.WhenAll(list.ToArray()).ContinueWith(t => Console.WriteLine("执行完成"));
            // Task.Factory.ContinueWhenAll(list.ToArray()  t => Console.WriteLine("执行完成"));
            Console.WriteLine("主线程");
            Console.Read();
        }
    }
    

输出
从输出中可以看出,task 不会阻塞主线程
有一个需求,需要在 task 线程任意线程执行完成之后执行
class Program
    {
        static void Main(string[] args)
        {
            List<Task> list = new List<Task>();
            Task t1 = Task.Run(() => Console.WriteLine("A"));
            Task t2 = Task.Run(() => Console.WriteLine("B"));
            Task t3 = Task.Run(() => Console.WriteLine("C"));
            Task t4 = Task.Run(() => Console.WriteLine("D"));
            list.Add(t1);
            list.Add(t2);
            list.Add(t3);
            list.Add(t4);
           //  二选一即可
            Task.WhenAny(list.ToArray()).ContinueWith(t => Console.WriteLine("执行完成"));
            // Task.Factory.ContinueWhenAny(list.ToArray()  t => Console.WriteLine("执行完成"));
            Console.WriteLine("主线程");
            Console.Read();
        }
    }
    

输出
这个方法也不会阻塞主线程
Task 任务取消有一个下载任务已运行,但这个文件已经不需要了,需要取消这个下载任务
class Program
    {
        static void Main(string[] args)
        {
            var cts = new CancellationTokenSource();
            int i;
            Task t1 = new Task(() =>
            {
                i = 0;
                while (!cts.IsCancellationRequested)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine($"下载中:{i  }%");
                    if(cts.IsCancellationRequested)
                        Console.WriteLine("下载已取消");
                }
            });
            t1.Start();
            // cts.Cancel();    //  立刻取消
            cts.CancelAfter(1000 * 10);  // 10秒后取消
            Console.Read();
        }
    }
    

输出
除了使用 if 语句输出 下载已取消,CancellationTokenSource 也有一个自带的注册任务取消事件
class Program
    {
        static void Main(string[] args)
        {
            var cts = new CancellationTokenSource();
            int i;
            Task t1 = new Task(() =>
            {
                i = 0;
                while (!cts.IsCancellationRequested)
                {
                    Thread.Sleep(1000);
                    Console.WriteLine($"下载中:{i  }%");
                }
            });
            // 取消后执行
            cts.Token.Register(() =>
            {
                Console.WriteLine("下载已取消");
            });
            t1.Start();
            cts.CancelAfter(1000 * 10);
            Console.Read();
        }
    }
    

输出
异步方法(async/await)class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(GetContentAsync().Result);
            Console.Read();
        }
				// 不会阻塞线程
        async static Task<string> GetContentAsync()
        {
            Encoding GB2312 = Encoding.GetEncoding("GB2312");
            Encoding GBK = Encoding.GetEncoding("GBK");
            FileStream fs = new FileStream(@"D:\1.txt"  FileMode.Open);
            byte[] bytes = new byte[fs.Length];
            Console.WriteLine("开始读取文件");
            int len = await fs.ReadAsync(bytes 0 bytes.Length);
            string res = Encoding.UTF8.GetString(bytes);
            return res;
        }
    }
    

输出
Task 对ThreadPool做了封装,主要是为了更好地控制线程池中的线程
完!坚持and放弃,我选择坚持




