天天看点

多线程学习笔记2多线程学习笔记2

多线程学习笔记2

主要内容:Thread的API使用 ThreadPool线程池的使用

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 多线程学习2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btn_Thread_Click(object sender, EventArgs e)
        {
            Console.WriteLine($"btn_Thread_Click Start {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
            Action action = () => this.DoSomethingLong("btnThread_Click");

            ThreadStart threadStart = () => this.DoSomethingLong("btnThread_Click");
            Thread thread = new Thread(threadStart);
            thread.Start();
            //Thread不带返回值
            //thread.Suspend();//线程暂停执行(挂起)目前已经不使用这种方式了
            //thread.Resume();//线程唤醒 目前已经不使用这种方式了
            //try
            //{
            //    thread.Abort();//线程销毁,方式是抛异常。也不建议使用,不一定即使,并且有些命令执行了就停不下来,
            //}
            //catch(Exception ex)
            //{
            //    //
            //    Thread.ResetAbort();//取消异常继续计算
            //}
            //如果用的就需要使用try catch,捕获异常
            //以上三种方法不推荐使用

            //线程等待
            //thread.Join();//当前线程等待thread完成
            Console.WriteLine("等待500ms");
            thread.Join(500);//最多等500ms

            while(thread.ThreadState==ThreadState.Stopped)
            {
                Thread.Sleep(100);//当前线程休息100ms
            }

            Console.WriteLine(thread.IsBackground); //默认是前台线程,启动之后一定要完成任务,才退出
            thread.IsBackground = true;//后台线程,随着进程退出

            thread.Priority = ThreadPriority.Highest;//线程优先级,CPU会优先执行等级较高的线程,但不是先只执行优先级最高的,还是同时执行,用处不是很大

            this.ThreadWithCallback(() => Console.WriteLine($"这是action {Thread.CurrentThread.ManagedThreadId.ToString("00")}"),
            () => Console.WriteLine($"这是callback {Thread.CurrentThread.ManagedThreadId.ToString("00")}"));

            Func<int> func = this.ThreadWithReturn<int>(() =>
            {
                Thread.Sleep(2000);
                return DateTime.Now.Millisecond;
            });

            Console.WriteLine("子线程执行完毕");
            int iResult = func.Invoke();
            Console.WriteLine(iResult);

            Console.WriteLine($"btn_Thread_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        }

        private void DoSomethingLong(string str)
        {
            for(int i=1;i<10;i++)
            {
                Thread.Sleep(200);      
            }
            Console.WriteLine(str + "  " + Thread.CurrentThread.ManagedThreadId.ToString("00"));
        }

        //启动子线程计算--完成委托后,该线程去执行后续回调委托

        private void ThreadWithCallback(Action act, Action callback)
        {
            Thread thread = new Thread(() =>
            {
                act.Invoke();
                callback.Invoke();
            });
            thread.Start();
        }

        //带返回值的异步调用,需要获取返回值
        private Func<T> ThreadWithReturn<T>(Func<T> func)
        {
            T t = default(T);
            Thread thread = new Thread(() =>
            {
                t = func.Invoke();
            });
            thread.Start();
            return () =>
            {
                while (thread.ThreadState != ThreadState.Stopped)
                {
                    Thread.Sleep(200);
                }
                //thread.Join();等待线程结束
                return t;
            };
        }

        private void btn_ThreadPool_Click(object sender, EventArgs e)
        {
            Console.WriteLine($"btn_ThreadPool_Clickk Start {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
            //threadpool出现的原因 1 提供了太多的API,很难使用;2 无限使用线程,加以限制;3 重用线程,避免重复的创建和销毁
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));//启动线程

            //获取线程池的最大数目,工作线程和异步线程
            int workerThreads, completionPortThreads;
            ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
            Console.WriteLine($"workerThreads={workerThreads}  completionPortThreads={completionPortThreads}");

            //获取线程池的最小数目
            ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
            Console.WriteLine($"workerThreads={workerThreads}  completionPortThreads={completionPortThreads}");

            ThreadPool.SetMaxThreads(32, 32);//设置最大线程数
            ThreadPool.SetMinThreads(4, 4);//设置最小线程数

            ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
            Console.WriteLine($"workerThreads={workerThreads}  completionPortThreads={completionPortThreads}");

            ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
            Console.WriteLine($"workerThreads={workerThreads}  completionPortThreads={completionPortThreads}");

            //ThreadPool没有直接对线程的操作,

            //ThreadPool线程等待的方法
            //类,包含一个bool属性
            //false--WaitOne等待--Set--true--WaitOne直接过去
            //true--WaitOne直接过去--Reset--false--WaitOne等待
            ManualResetEvent manualResetEvent = new ManualResetEvent(false);//可以保证线程安全,相比与自己创建的bool变量
            ThreadPool.QueueUserWorkItem(t =>
            {
                this.DoSomethingLong("btn_ThreadPool_Click");
                manualResetEvent.Set();
                //manualResetEvent.Reset();
            });
            manualResetEvent.WaitOne();
            manualResetEvent.Reset();//设置为false
            //一般情况下不要阻塞线程池的线程:错误实例
            //之前设置了线程池的最大数量为16,下面的程序阻塞了16个线程后程序就会卡死
            for(int i=0;i<20;i++)
            {
                int k = i;
                ThreadPool.QueueUserWorkItem(t =>
                {
                    Console.WriteLine(k);
                    if(k<18)
                    {
                        manualResetEvent.WaitOne();
                    }
                    else
                    {
                        manualResetEvent.Set();//设置为true
                    }
                });
            }
            if (manualResetEvent.WaitOne())
            {
                Console.WriteLine("没有锁死......");
            }
            Console.WriteLine("ThreadPool.QueueUserWorkItem执行完成后才执行");

            //线程重用
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));

            Thread.Sleep(10 * 1000);
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));
            ThreadPool.QueueUserWorkItem(t => this.DoSomethingLong("btn_ThreadPool_Click"));

            Console.WriteLine($"btn_ThreadPool_Click End {Thread.CurrentThread.ManagedThreadId.ToString("00")}");
        }
        
    }
}

           

继续阅读