C#winform單線程事例與多線程事例


通過例子編寫,用winform編寫的,講解單線程與多線程使用,用於異步加載數據,界面不會卡死,數據在后台默認加載,給用戶更好的體驗。稍后會附加完整代碼。

1、先不用線程,顯示一個求和,計算過程中要停留1秒后繼續計算。如果不用多線程頁面就會卡死,直到計算完成后才會響應。一個button按鈕,一個label 

界面:

代碼如下:

  #region 不用線程情況
        private void button1_Click(object sender, EventArgs e)
        {
            //不用線程點擊按鈕,窗體會卡死,10秒后恢復
            int sum = 0;
            for (int i = 0; i < 10; i++)
            {
                sum = sum + i;
                label3.Text = sum.ToString();
                Thread.Sleep(1000);//休息1秒
            }
        }
        #endregion

2、用單線程進行處理,單獨開啟一個進線程啟動,進行每個2秒鍾進行計數顯示,並且窗體不會死。界面是一個button 兩個 label。

界面:

代碼:

    #region 多線程中,單獨一個線程運行
        private void btnD_Click(object sender, EventArgs e)
        {
            //多線程中,單獨一個進程啟動,進行每個2秒鍾進行計數顯示,並且窗體不會死。
            Thread t = new Thread(new ThreadStart(OneThreadSum));//開啟線程
            t.IsBackground = true;//附加主線程,主線程關閉后,子線程也跟着關閉,簡單理解就是窗體關閉,啟動線程也跟着關閉。
            t.Start();
        }
        private void OneThreadSum()
        {
            try
            {
                Invoke(this, delegate
                {
                    //按鈕變為灰色 防止按鈕多次點擊
                    //給控件賦值就需要使用invoke
                    this.btnD.Enabled = false;
                });
                  
                for (int i = 0; i < 10; i++)
                {
                    Invoke(this, delegate
                    {
                        //通過代理賦值,通過這種方式,界面和窗口就不會卡死,窗口先展示出來,然后數據過后加載。
                        //給控件賦值就需要使用invoke
                        label2.Text = i.ToString();
                    });
                    Thread.Sleep(2000);//休息2秒
                }
            }
            catch (Exception ex)
            {

                throw;
            }
            finally 
            {
                //給控件賦值就需要使用invoke
                Invoke(this, delegate
                {
                    this.btnD.Enabled = true;
                });
            }
            
        }
        /// <summary>
        /// 在線程中通過代理給控件賦值
        /// </summary>
        /// <param name="col"></param>
        /// <param name="method"></param>
        public void Invoke(Control col, MethodInvoker method)
        {
            if (!col.IsHandleCreated) return;//當前控件是否被創建
            if (col.IsDisposed) return;//當前控件是否被銷毀
            if (col.InvokeRequired) col.Invoke(method);//是否允許被請求
            else method();
        }
        #endregion

 3、模擬餐館來人吃飯,客人來了點菜是一個線程,客人就餐時一個線程,客人結賬時一個線程,一共3個線程,各自處理各自的事情,一個客人名稱textbox, 一個客人來了button,一個啟動初始化按鈕,listbox1 代表點餐記錄 ,listbox2 代表就餐記錄 ,listbox3代表結賬記錄 。

界面:

代碼:

     #region 用多線程 不是單獨一個線程,以3個線程為例
        //模擬餐館來人吃飯,客人來了點菜是一個線程,客人吃飯時一個線程,客人結賬時一個線程,一共3個線程

        private void 啟動監聽線程_Click(object sender, EventArgs e)
        {
            啟動監聽線程.Enabled = false;//初始化只允許一次,否則會開啟很多線程,所以要灰色
            wait1 = new ManualResetEvent(false);//啟動信號,等待着。
            t1 = new Thread(new ThreadStart(F1)) { IsBackground = true };
            t1.Start();//初始化線程t1 點餐線程


            wait2 = new ManualResetEvent(false);
            t2 = new Thread(new ThreadStart(F2)) { IsBackground = true };
            t2.Start();//初始化線程t2 用餐線程


            wait3 = new ManualResetEvent(false);
            t3 = new Thread(new ThreadStart(F3)) { IsBackground = true };
            t3.Start();//初始化線程t3 結賬線程
        }
        private void 客人來了_Click(object sender, EventArgs e)
        {
            data1.Add(textBox1.Text);//這個時候客人來了,增加到list中。
            wait1.Set();//告訴服務員,客人來了,要開始點餐了。
        }
        private IList data1 = new ArrayList();//存儲來客人
        private Thread t1 = null;//點菜線程
        private ManualResetEvent wait1 = null;//信號,相當於服務員,客人來了需要告訴
        private void F1()
        {
            while (true)
            {
                //2秒鍾查詢一次。
                if (wait1.WaitOne(2000, false))
                {
                    if (data1 == null || data1.Count == 0)
                    {
                        //如果一個人都沒有的話,不需要點菜
                        Invoke(this, delegate
                        {
                            listBox1.Items.Add("無客人!");
                        });
                        wait1.Reset();//線程停止,繼續等待。
                        continue;//結束本次循環
                    }
                    //程序執行到這里說明有人,客人開始點餐。
                    string r = data1[0] as string;
                    Invoke(this, delegate
                    {
                        listBox1.Items.Add(r + "->開始點餐!");
                    });
                    Thread.Sleep(2000);


                    data2.Add(r);//增加到用餐list中
                    wait2.Set();//告訴可以開始用餐了。

                    data1.RemoveAt(0);//客人從隊列中移除
                }
            }
        }


        private IList data2 = new ArrayList();//存儲用餐人
        private Thread t2 = null;//用餐線程
        private ManualResetEvent wait2 = null;//信號,用餐信號
        private void F2()
        {
            while (true)
            {
                if (wait2.WaitOne(2000, false))
                {
                    if (data2 == null || data2.Count == 0)
                    {
                        Invoke(this, delegate
                        {
                            listBox2.Items.Add("無用餐人!");
                        });
                        wait2.Reset();
                        continue;
                    }
                    //程序執行到這里說明有人,客人開始用餐。
                    string r = data2[0] as string;

                    Invoke(this, delegate
                    {
                        listBox2.Items.Add(r + "->用餐中...!");
                    });
                    Thread.Sleep(3000);

                    data3.Add(r);//增加到結賬的list中
                    wait3.Set();//告訴客人可以開始結賬了

                    data2.RemoveAt(0);//客人從隊列中移除
                }
            }
        }


        private IList data3 = new ArrayList();//存儲結賬人
        private Thread t3 = null;//結賬線程
        private ManualResetEvent wait3 = null;//結賬信號
        private void F3()
        {
            while (true)
            {
                if (wait3.WaitOne(2000, false))
                {
                    if (data3 == null || data3.Count == 0)
                    {
                        Invoke(this, delegate
                        {
                            listBox3.Items.Add("無結賬人!");
                        });
                        wait3.Reset();
                        continue;
                    }
                    //程序執行到這里說明有人,客人開始結賬。
                    string r = data3[0] as string;

                    Invoke(this, delegate
                    {
                        listBox3.Items.Add(r + "->結賬買單!");
                    });
                    Thread.Sleep(4000);

                    data3.RemoveAt(0);//客人從隊列中移除
                }
            }
        }

        /// <summary>
        /// 在線程中通過代理給控件賦值
        /// </summary>
        /// <param name="col"></param>
        /// <param name="method"></param>
        public void Invoke(Control col, MethodInvoker method)
        {
            if (!col.IsHandleCreated) return;//當前控件是否被創建
            if (col.IsDisposed) return;//當前控件是否被銷毀
            if (col.InvokeRequired) col.Invoke(method);//是否允許被請求
            else method();
        }

        #endregion

 csdn 源碼下載鏈接:https://download.csdn.net/download/njxiaogui/12514492


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM