WinForm中新開一個線程操作 窗體上的控件(跨線程操作控件)


最近在做一個winform的小軟件(搶票的...)。登錄窗體要從遠程web頁面獲取一些數據,為了不阻塞登錄窗體的顯示,開了一個線程去加載數據遠程的數據,會報一個錯誤"線程間操作無效: 從不是創建控件“lbl_loading_msg”的線程訪問它。"百度一下,原來從.net framework 2.0開始,為了安全,不允許跨線程操作控件。解決辦法如下:
1、聲明一個擁有委托類型的方法,作為代理 操作控件的代碼:

        /// <summary>
        /// 在線程中操作窗體的控件
        /// </summary>
        /// <param name="action"></param>
        private void OpeMainFormControl(Action action)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(action); //返回主線程(創建控件的線程)
            }
            else
            {
                action();
            }
        }

2、然后在線程中,只要是對控件的操作都委托給上面的方法執行,不管是讀取還是賦值:

            Thread t = new Thread(new ThreadStart(delegate()
            {
                //執行一段費時的代碼
                //......
                //線程中操作 控件,委托給invoker
                OpeMainFormControl(delegate()
                {
                    this.lbl_loading_msg.Visible = false; //隱藏驗證碼加載中...的提示
                    this.toolStripStatusLabel1.Text = ""; //清空狀態欄
                    this.btnlogin.Enabled = true;    //啟用登錄按鈕
                });
            }));
            t.Start(); //啟動線程

上面代碼需要注意的是:僅對控件操作的代碼委托給this.invoker。上面委托操作的方法中的this是窗體對象,也就是創建控件的線程,this.invoker(action)就是將代碼交給它來執行。這樣就操作控件的代碼就交給了創建控件的線程來執行了。我們不要將費時操作的代碼也交給this.invoker來執行,不然就失去了線程的意義了(相當於沒有開線程)。this.inoker又回到了主線程,會產生阻塞!下面代碼會阻塞:

                //將費時的代碼也委托給 主線程(創建控件的線程)來執行,會阻塞窗體
                OpeMainFormControl(delegate()
                {
                //執行一段費時的代碼
                //......
                //線程中操作 控件,委托給invoker
                
                    this.lbl_loading_msg.Visible = false; //隱藏驗證碼加載中...的提示
                    this.toolStripStatusLabel1.Text = ""; //清空狀態欄
                    this.btnlogin.Enabled = true;    //啟用登錄按鈕
                });

還有一點:如果對控件的操作代碼沒有委托給創建它的線程來執行(比如實例化另外一個窗口,show出來),它的一些設置會不起作用,比如:窗體初始顯示位置等...


免責聲明!

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



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