• Thread线程总结


    一、使用Thread类来实现

    Thread类的实现方式,在C# .NetFramework刚出的时候就已经存在了,起初刚开始的程序员都使用这种方式,但经历后面几个.NetFramework的版本更新,实现方式变的更多了。

    public static void TestThread()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
    
        Console.WriteLine("主线程id为:{0},总耗时为:{1}", Thread.CurrentThread.ManagedThreadId,watch.ElapsedMilliseconds);
    
        Thread thread = new Thread(TestAction);
        //设置线程相关属性
        thread.IsBackground = true;
        thread.Name = "Test";
        //启动线程
        thread.Start();
    
        watch.Stop();
        Console.WriteLine("主线程id为:{0},总耗时为:{1}", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
    }
    /// <summary>
    /// 线程执行的方法
    /// </summary>
    private static void TestAction()
    {
        //这里实现线程处理的相关业务
        Console.WriteLine($"子线程Thread({ Thread.CurrentThread.Name})的线程id为:{ Thread.CurrentThread.ManagedThreadId}");
    }
    View Code

    运行结果:

    一个任务(Task) 是可以设置多个延续任务的,这些任务是并行的,例如:

     static void Main()
            {
                Task task = new Task(() =>
                {
                    Console.WriteLine("     第一个任务");
                    Thread.Sleep(TimeSpan.FromSeconds(1));
                });
                // 任务①
                task.ContinueWith(t =>
                {
                    for (int i = 0; i < 5; i++)
                    {
                        Console.WriteLine($"    任务① ");
                        Thread.Sleep(TimeSpan.FromSeconds(1));
                    }
                });
                // 任务②
                task.ContinueWith(t =>
                {
                    for (int i = 0; i < 5; i++)
                    {
                        Console.WriteLine($"     任务②");
                        Thread.Sleep(TimeSpan.FromSeconds(1));
                    }
                });
                // 任务① 和 任务② 属于同级并行任务
                task.Start();
                }
    View Code

    多个线程等待的情况

            static void Main(string[] args)
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
    
                Console.WriteLine("主线程id为:{0},总耗时为:{1}", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
    
                List<IAsyncResult> list = new List<IAsyncResult>();
                for (int i = 0; i < 5; i++)
                {
                    string name = string.Format("我是{0}", i);
                    Action myFunc = () =>
                    {
                        TestThread(name);
                    };
                    var asyncResult = myFunc.BeginInvoke(null, null);
                    list.Add(asyncResult);
                }
                //下面是线程等待
                foreach (var item in list)
                {
                    item.AsyncWaitHandle.WaitOne(-1);
                }
    
                watch.Stop();
                Console.WriteLine("主线程id为:{0},总耗时为:{1}", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
                Console.ReadLine();
            }
    
            static void TestThread(string name)
            {
                Thread.Sleep(1000);
                Console.WriteLine("子线程id为:{0},当前时间为:{1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
            }
    View Code

     结果:

            List<ManualResetEvent> manualEvents = new List<ManualResetEvent>();
            static void Main(string[] args)
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                Console.WriteLine("-----------------Thread多线程  --------------------------");
                Console.WriteLine("-----------------开始 主线程id为:{0}  --------------------------", Thread.CurrentThread.ManagedThreadId);
                List<Thread> threadList = new List<Thread>();
    
                Thread myThread = new Thread(() =>
                {
                    Console.WriteLine("我是子线程1");
                    Thread.Sleep(2000);
                });
                //myThread.IsBackground = true;   //设置为后台线程,主程序关闭所有线程均关闭
                myThread.Start();
    
                Thread myThread1 = new Thread(() =>
                {
                    Console.WriteLine("我是子线程2");
                    Thread.Sleep(2000);
                });
                //myThread1.IsBackground = true;   //设置为后台线程,主程序关闭所有线程均关闭
                myThread1.Start();
    
                threadList.Add(myThread);
    
                //利用join方法进行线程等待
                foreach (Thread thread in threadList)
                {
                    thread.Join();
                }
                watch.Stop();
                Console.WriteLine("----------------- 结束 主线程id为:{0}  总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
                Console.ReadKey();
            }
        }
    View Code

    结果:

    二、ThreadPool 线程池实现

    public static void TestThreadPool()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
    
        Console.WriteLine("主线程id为:{0},总耗时为:{1}", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
    
        //可以设置相关属性
        ThreadPool.SetMinThreads(5, 10);
        ThreadPool.SetMaxThreads(6, 10);
    
        //通过线程池自动分配线程执行对应的业务功能
        ThreadPool.QueueUserWorkItem(TestAction);
    
        Console.WriteLine("主线程id为:{0},总耗时为:{1}", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
    }
    private static void TestAction(object state)
    {
        //这里实现线程处理的相关业务
        Console.WriteLine($"子线程Thread({Thread.CurrentThread.Name})执行相关业务操作....{Thread.CurrentThread.ManagedThreadId}");
    }
    View Code

    运行结果:

    ThreadPool的使用是不是感觉比较简单,但是就是因为太简单了,在业务中有些需求得不到满足,比如试着控制线程顺序;

    三、Delegate 实现的多线程

            public static void TestDelegateThread()
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
    
                Console.WriteLine("主线程id为:{0},总耗时为:{1}", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
    
                //定义一个强类型委托, 可以自定义委托
                Action action = TestAction;
                //开始异步操作,其实内部是开启了子线程,看线程id不一样就明白了
                IAsyncResult asyncResult = action.BeginInvoke(CallBack, null);
                var aa=asyncResult.IsCompleted; //判读是否执行完成
                //asyncResult.AsyncWaitHandle.WaitOne(); //阻塞当前线程,直到收到信号量
    
                Console.WriteLine("主线程id为:{0},总耗时为:{1}", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
            }
            //子线程执行完成时的回调
            public static void CallBack(IAsyncResult ar)
            {
                Console.WriteLine($"子线程{ Thread.CurrentThread.ManagedThreadId}执行完毕");
            }
            private static void TestAction()
            {
                Thread.Sleep(2000);
                //这里实现线程处理的相关业务
                Console.WriteLine($"子线程Thread({Thread.CurrentThread.Name})执行相关业务操作....{Thread.CurrentThread.ManagedThreadId}");
                
            }
    View Code

    运行结果:

    注:  这种方式在.NetCore环境不支持,提示平台不支持。

    线程内 给C# 窗体控件赋值

     //1、声明委托类型,线程中设置Text 
    public delegate void SetTextDelegate(string name, string text); 
    
     //2、给控件赋值
     public void SetText(string name, string text)
     {
          Control c = FindComponent(name);//查找name的控件
           if (c != null) c.Text = text; //给text赋予值
     }
    
     //3、可以线程内调用
    Invoke(new SetTextDelegate(SetText), new object[] { "textBox1", "赋予控件文本的值!" });

     Thread  单独传递参数

    public void ExecSelf()
    {
        Thread t = new Thread(() => PubUploadMethod(docCode, sType));
        t.Start();
    }
    
     //上传数据组装
    
    public JsonResult PubUploadMethod(string idStr,string sType)
    {
    
    }

    使用InvokeDelegate方式

    private delegate void InvokeDelegate();//上传后刷新数据的委托
    
    public void SyncAllEmployee()
    {
        try
        {
            CommonHelper.SyncAllEmployee();
            this.BeginInvoke(new InvokeDelegate(sx));
        }
        catch (Exception ex)
        {
            Program.GetExceptionMsg(ex, null);
        }
    }
    
    public void sx()
    {
      //我是刷新的方法  
    }

     窗体间

    public const int CUSTOM_MESSAGE = 0X400 + 1001;
    
    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    private static extern IntPtr SendMessage(int hWnd, int msg, IntPtr wParam, IntPtr lParam);
    [DllImport("User32.dll", EntryPoint = "FindWindow")]
    private static extern int FindWindow(string lpClassName, string lpWindowName);
    
    public static void SendMsgToMainForm(int MSG, string windowName, int msgType)
    {
        int WINDOW_HANDLER = FindWindow(null, windowName);
        if (WINDOW_HANDLER == 0)
        {
            MessageBox.Show("未找到指定窗体");
        }
        long result = SendMessage(WINDOW_HANDLER, CUSTOM_MESSAGE, new IntPtr(msgType), IntPtr.Zero).ToInt64();
    }
    
    //调用
    SendMsgToMainForm(CUSTOM_MESSAGE, main_window_name, 8000);
    protected override void WndProc(ref System.Windows.Forms.Message msg)
    {
        switch (msg.Msg)
        {
            case Public_Class.CUSTOM_MESSAGE:
                switch (msg.WParam.ToString())
                { 
                    case "8000":   
                        //可以调用窗体内控件
                        break;
                    case "8001":
                        break;
                    default:
                        break;
                }
                break;
            default:
                base.WndProc(ref msg);
                break;
        }
    }

    其他

      

    作者:chenze
    出处:https://www.cnblogs.com/chenze-Index/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
    如果文中有什么错误,欢迎指出。以免更多的人被误导。
  • 相关阅读:
    java-oop集合map
    IDEA启动Tomcat报错
    1.IDEM的快捷键
    1.idea快捷键
    14.
    13.级联一对多
    12.动态SQL
    11.动态参数
    10.主键回填
    9.参数的传递
  • 原文地址:https://www.cnblogs.com/chenze-Index/p/11593136.html
Copyright © 2020-2023  润新知