zoukankan      html  css  js  c++  java
  • 番外篇之多线程

    视频一:线程的介绍及线程的基本语法

               1.线程的创建
                   Thread th = new Thread(Func);//创建线程
                   th.Start();//启动线程
                   private void Func()//线程执行的方法
                   {///填写方法
                   }

                2.学习线程最经典的错误

                    2.1线程间操作无效:从不是创建控件“label1”的线程访问它。

                         解决方案:忽略异常,跨线程操作。 Control.CheckForIllegalCrossThreadCalls = false;//忽略跨线程间的调用,不推荐大家使用,它可能会引发一些未知的异常。

                     2.2创建窗口句柄时出错

                          引发原因:窗口被结束,但是线程还未结束。虽然看着窗体已经结束,但是任务管理器中一样可以看到进程依然存在在运行。 UI关闭后,没有通知后台线程结束,主线程未完全退出,因为只要有一条子线程还在运行,那么它(子线程)将阻塞主线程关闭。

                         解决方案:th.IsBackground = true;//当前线程为后台线程,则会完全退出程序                

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Threading;
    using System.Windows.Forms;
    
    namespace 番外篇之多线程
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                Control.CheckForIllegalCrossThreadCalls = false;//忽略跨线程间的调用,不推荐大家使用,它可能会引发一些未知的异常
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
               
            }
            private void Func()//线程执行的方法
            {
                for (int i = 0; i < 100000; i++)
                {
                    label1.Text = i.ToString();
                }
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Thread th = new Thread(Func);//创建线程
                th.IsBackground = true;//当前线程为后台线程
                th.Start();//启用线程
            }
        }
    }
    View Code

    视频二:线程的高级写法接受任意参数

               1.参数的传递,object类型的方式,而且仅能一个参数

                  private void GetInfo(object strinfo)
                {
                MessageBox.Show(strinfo.ToString());
                 }
                private void button1_Click(object sender, EventArgs e)
                {
                string strinfo = "Andrew";
                Thread thread = new Thread(GetInfo);
                thread.Start((object)strinfo);
               }

               2.参数的传递,非object类型的方式,且可以多个参数

                   private void GetInfo(object strinfo,string str)
                  {
                  MessageBox.Show(strinfo.ToString());
                  }
                 private void button1_Click(object sender, EventArgs e)
                 {
                  string strinfo = "Andrew";
                  Thread thread = new Thread(new ThreadStart(delegate { GetInfo((object)strinfo, strinfo); }));
                  thread.Start();
                 }

              3.使用线程池,缺点:线程池是不可以控制的。

                   private void GetInfo(object strinfo,string str)
                {
                MessageBox.Show(strinfo.ToString());
                }
                private void button1_Click(object sender, EventArgs e)
                {
                string strinfo = "Andrew";
                //Thread thread = new Thread(GetInfo);
                //thread.Start((object)strinfo);
                //Thread thread = new Thread(new ThreadStart(delegate { GetInfo((object)strinfo, strinfo); }));
                //thread.Start();
                ThreadPool.QueueUserWorkItem(p => { GetInfo(strinfo, strinfo); });
                ThreadPool.QueueUserWorkItem(new WaitCallback(delegate{ GetInfo(strinfo, strinfo); }));
               }

                4.Thread.Sleep(100);//睡眠,挂起 参数(int)单位毫秒,是全局有效。

     视频三:稍微高级点的线程控制以及多线程常用的场景

                1.线程暂停及恢复

                  1.1 th.Suspend();////挂起线程

                         if (th.ThreadState != ThreadState.Suspended)  //本来判断是否为后台线程的,但是由于线程处理会有一个时间(就会造成线程无法停止),所以直接判断是不是被挂起
                         {
                        //挂起后台线程
                        th.Suspend();
                         }

                  1.2  th.Resume();////继续挂起的线程

                          if (th != null && th.ThreadState!= ThreadState.Running) //判断是否为后台线程,是否被挂起
                          {
                          th.Resume(); //继续线程
                          }

                   1.3  th.TreadState////线程的状态枚举

               2.应用场景 Post程序,需要输入验证码

                  先开启线程,来执行get请求,得熬验证码图像,挂起这个线程,等待验证码的输入        

               3.lock(this) {}//锁

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    
    namespace Thread_Dom
    {
        public partial class Form1 : Form
        {
            private AutoResetEvent m_autoEvent;
            public Form1()
            {
                InitializeComponent();
                Control.CheckForIllegalCrossThreadCalls = false; //跨线程访问From控件中的Lab,最好使用委托来在UI显示.最好不用这种方式,容易造成线程间安全问题.
            }
    
            private void Form1_Load(object sender, EventArgs e)
            { 
            } 
            Thread th;
            private void btnOk_Click(object sender, EventArgs e)
            {
                btnOk.Enabled = false;
                #region 同步后台线程间挂起恢复 | 启动线程 
                //同步线程
                th = new Thread(Funcs);
                th.IsBackground = true;
                th.Start(); 
                #endregion 
                
            }
            private void Funcs(object o)
            {
                
                for (int i = 0; i < 99999999; i++)
                {
                    Thread.Sleep(100);
                    labnum.Text = i.ToString();
    
                }
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                button1.Enabled = false;
                btnOk.Enabled = true;
                #region 同步后台线程间挂起恢复 | 暂停线程
             
                
               // MessageBox.Show("暂停线程..");
                if (th.ThreadState != ThreadState.Suspended)  //本来判断是否为后台线程的,但是由于线程处理会有一个时间(就会造成线程无法停止),所以直接判断是不是被挂起
                {
                    //挂起后台线程
                    th.Suspend();
                }
                
                #endregion
              
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                button1.Enabled = true;
                #region 同步后台线程间挂起恢复 | 恢复线程
               
                //MessageBox.Show("恢复线程..");    //线程间调用messagebox会直接阻塞线程,所以看起来不同步,注释掉就ok
                
                 
                if (th != null && th.ThreadState!= ThreadState.Running) //判断是否为后台线程,是否被挂起
                {
                    th.Resume(); //继续线程
                }
                #endregion
            }
    
            private void btnStart_Click(object sender, EventArgs e)
            {
                 
            }
            object o = new object();
            bool b = false;
            private void Post()
            {
                for (int i = 0; i <10; i++)
                {
                    //5出现验证码
                    if (i == 5)
                    {
                        while (true)
                        {
                            if (b!=false)
                            {
                                continue;
                            }
                        }
                       // thread.Suspend();
                        //接收验证码的输入.
                        string vcode = txtVcode.Text;
                        //.....
                    }
                    
                }
            }
            Thread thread;
            private void button3_Click(object sender, EventArgs e)
            {
                thread = new Thread(new ThreadStart(delegate
                {
                    Post();
                }));
                thread.Start();
            }
    
            private void txtVcode_TextChanged(object sender, EventArgs e)
            {
                if (txtVcode.Text.Length == 4)
                { 
                    thread.Resume();
                }
            }
    
            private void txtVcode_KeyPress(object sender, KeyPressEventArgs e)
            {
                 if(e.KeyChar==(char)13)
                 {
                     thread.Resume();
                 }
            }
    
            
        }
    }
    View Code

               4.提供类的好处:帮助理解他人是如何处理线程

                  两种情况:固定线程数,不固定任务数

                                固定任务数,自动计算线程数

                  缺点:无法重复利用线程

                 

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Threading;
    
    namespace ThreadCallBack
    {
        /// <summary>
        /// 线程任务
        /// </summary>
        public class ThreadTask
        {
            /// <summary>
            /// 分页多线程
            /// </summary>
            /// <param name="ThreadIndex">线程序号</param>
            /// <param name="ExeCount">一条线程需要执行程序的个数</param>
            /// <param name="ThreadCount">线程总数</param>
            /// <param name="list"></param>
            public void ThreadRun(int ThreadIndex, int ExeCount, int ThreadCount, List<string> list)
            {
    
                if (ThreadIndex < ThreadCount)
                {
                    for (int i = (ThreadIndex - 1) * ExeCount; i < (ThreadIndex) * ExeCount; i++)
                    {
                        Console.WriteLine("当前线程:     " + Thread.CurrentThread.Name + "           执行任务I--" + list[i]);
    
                    }
                }
                else
                {
                    for (int i = (ThreadIndex - 1) * ExeCount; i < list.Count; i++)
                    {
                        Console.WriteLine("当前线程:     " + Thread.CurrentThread.Name + "          执行任务I --" + list[i]);
                    }
    
                }
    
            }
        }
    }
    View Code
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    
    namespace ThreadCallBack
    {
        delegate int GetRes(int i, int j);
        public partial class Form1 : Form
        {
            GetRes getres;
            public Form1()
            {
                //懒得写委托了.
                Control.CheckForIllegalCrossThreadCalls = false;
                InitializeComponent();
            }
            private int sum(int i, int j)
            {
                return i + j;
            }
            private void button1_Click(object sender, EventArgs e)
            {
                AsyncCallback async = new AsyncCallback(GetRes4Async);
                getres.BeginInvoke(1, 2, async, null);
    
            }
            private void GetRes4Async(IAsyncResult iasync)
            {
                if (iasync.IsCompleted)
                {
                    //完成
                    int res = getres.EndInvoke(iasync);
                    resLab.Text = res.ToString(); 
                }
            }
            private void Form1_Load(object sender, EventArgs e)
            {
                getres = new GetRes(sum);
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                List<string> slist = new List<string>();
                for (int i = 0; i < 139999; i++)
                {
                    slist.Add(i.ToString());
                }
                 
                //分页定律    
                //ThreadIndex 第几页   第几条线程
                decimal ExeCount = 99999; //每页显示多少个    需要执行程序的个数  分几次执行,一次处理多少条.
    
                int ThreadCount = int.Parse(Math.Ceiling((decimal)(slist.Count / ExeCount)).ToString()); //计算线程总数
                Thread[] thd = new Thread[ThreadCount];
                for (int ThreadIndex = 1; ThreadIndex < ThreadCount + 1; ThreadIndex++)
                {
                    int thIndex = ThreadIndex - 1;
                    ThreadTask task = new ThreadTask();
                    thd[thIndex] = new Thread(new ThreadStart(delegate
                    {
                        task.ThreadRun(ThreadIndex, int.Parse(ExeCount.ToString()), ThreadCount, slist);
    
                    }));
                    thd[thIndex].Name = thIndex.ToString() + "------>Name";
                    thd[thIndex].Start();
                    Thread.Sleep(10);
                    
                }
    
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                int threadCount = (int)ThreadupDown.Value; //线程数
                List<string> slist = new List<string>();
                for (int i = 0; i < 139999; i++)
                {
                    slist.Add(i.ToString());
                }
                Thread[] thd = new Thread[threadCount];
                //任务数/线程数 = 单条线程执行的任务数
                int ExeCount = int.Parse(Math.Ceiling(((decimal)slist.Count / threadCount)).ToString());
                //从1开始的目的就是执行第一批(比较好计算)..下面继续-1,就是线程下标..这段代码写的比较2..
                for (int ThreadIndex = 1; ThreadIndex < threadCount + 1; ThreadIndex++)
                {
                    int thIndex = ThreadIndex - 1;
                    ThreadTask task = new ThreadTask();
                    thd[thIndex] = new Thread(new ThreadStart(delegate
                    {
                        task.ThreadRun(ThreadIndex, ExeCount, threadCount, slist); 
                    }));
                    thd[thIndex].Name = thIndex.ToString() + "------>Name";
                    thd[thIndex].Start();
                    Thread.Sleep(10); 
                }
    
            }
    
        }
    }
    View Code

       

    视频教程出自:http://www.xuanjics.com/thread-67-1-1.html

                        玄机论坛的地址:www.xuanjics.com  原创作者:君临

                        QQ交流群:16885911  

                    

  • 相关阅读:
    设计模式之解释器模式
    设计模式之中介者模式
    设计模式之职责链模式
    设计模式之命令模式
    设计模式之迭代器模式
    设计模式之备忘录模式
    设计模式之状态模式
    【转】CSS中position属性( absolute | relative | static | fixed )详解
    【转】fiddler-http协议调试代理工具
    TCP/IP、Http、Socket的区别
  • 原文地址:https://www.cnblogs.com/Time_1990/p/4053459.html
Copyright © 2011-2022 走看看