1 Winform 異步更新控件


剛才看到有人問為了winfrom中,在大數據綁定的時候出現畫面假死的狀態,為了解決這個問題希望通過再開一個線程來給控件綁定數據,可是畫面還是會假死。
現在看到的方法有
1.掩耳盜鈴法(Control.CheckForIllegalCrossThreadCalls = false;)

C# code ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using  System;
using  System.Threading;
using  System.Windows.Forms;
 
namespace  ThreadTest
{
     public  partial  class  Form1 : Form
     {        
 
         public  Form1()
         {
             InitializeComponent();
             Control.CheckForIllegalCrossThreadCalls =  false ; //這一行是關鍵      
         }
        
 
         private  void  btnSet_Click( object  sender, EventArgs e)
         {           
             Thread t =  new  Thread( new  ParameterizedThreadStart(SetTextBoxValue));
             t.Start( "Hello World" );
         }
 
 
         void  SetTextBoxValue( object  obj) 
         {
             this .textBox1.Text = obj.ToString();
         }        
     }
}


這種方法是最方便,實現最簡單的方式,但是這樣等於是線程之間是去了限制,子線程能夠直接控制父線程的控件,會出現線程之間的沖突,不是好的實現方式
2.利用BackgroundWorker

C# code ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
using  System;
using  System.ComponentModel;
using  System.Windows.Forms;
 
namespace  ThreadTest
{
     public  partial  class  Form1 : Form
     {
         public  Form1()
         {
             InitializeComponent();            
         }       
 
         private  void  btnSet_Click( object  sender, EventArgs e)
         {
             //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
             using  (BackgroundWorker bw =  new  BackgroundWorker())
             {
                 bw.RunWorkerCompleted +=  new  RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                 bw.DoWork +=  new  DoWorkEventHandler(bw_DoWork);
                 bw.RunWorkerAsync( "Hello World" );
             }
         }
 
         void  bw_DoWork( object  sender, DoWorkEventArgs e)
         {
             //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
             e.Result = e.Argument; //這里只是簡單的把參數當做結果返回,當然您也可以在這里做復雜的處理后,再返回自己想要的結果(這里的操作是在另一個線程上完成的)
         }
 
         void  bw_RunWorkerCompleted( object  sender, RunWorkerCompletedEventArgs e)
         {
             //這時后台線程已經完成,並返回了主線程,所以可以直接使用UI控件了
             this .textBox1.Text = e.Result.ToString();
             //MessageBox.Show(Thread.CurrentThread.ManagedThreadId.ToString());
         }       
     }    
}


這種方式只能在異步結束后給控件賦值,
--即bw_DoWork是異步處理,異步處理過程中不能給控件賦值
--bw_RunWorkerCompleted方法中可以給控件賦值,可是這個過程不是異步的,如果在bw_RunWorkerCompleted中加上一個System.Threading.Thread.Sleep(3000);畫面還是會假死
3.不使用BackgroundWorker,自己來寫線程來實現類似於BackgroundWorker的處理

子線程給主線程成員賦值的迷惑

C# code ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
         // 代碼中自己定義的按鈕(非顯示按鈕)
         private  Button testBtn =  new  Button();
 
         private  void  button1_Click( object  sender, EventArgs e)
         {
             Thread thr =  new  Thread(ControlParent);
             thr.Start();
         }
 
         private  void  ControlParent()
         {
             Thread.Sleep(3000);
             // 給自己定義的按鈕賦值沒有問題
             testBtn.Text =  "eeee" ;
             // 給畫面上顯示的按鈕賦值,InvalidOperationException錯誤(這里迷糊了,子線程不能直接給主線程賦值,那么主線程是什么?)
             this .button1.Text =  "asda" ; // InvalidOperationException!!!!!!!!!!!
         }


這里的兩個按鈕,同樣是屬於一個類,只不過一個顯示在畫面上,另一個只定義了沒有顯示,為什么一個賦值成功,另一個就是敗了,求大哥大姐們來個破解之法,感激不盡。
PS:窗體的this.BeginInvoke只能不阻塞后面代碼的執行,不能解決畫面假死






免責聲明!

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



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