程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#子線程更新UI控件的方法總結,

C#子線程更新UI控件的方法總結,

編輯:C#入門知識

C#子線程更新UI控件的方法總結,


在winform C/S程序中經常會在子線程中更新控件的情況,桌面程序UI線程是主線程,當試圖從子線程直接修改控件屬性時會出現“從不是創建控件的線程訪問它”的異常提示。

跨線程更新UI控件的常用方法有兩種:

1.使用控件自身的invoke/BeginInvoke方法

2.使用SynchronizationContext的Post/Send方法更新

 

1.使用控件自身的invoke/BeginInvoke方法

Control類實現了ISynchronizeInvoke 接口,我們看該接口的定義:

Control類的invoke方法有兩個實現

Object Invoke(Delegate); //在擁有此控件的基礎窗口句柄的線程上執行指定的委托

Object Invoke(Delegate,Object[] );

可以看出繼承Control類的UI控件都可以使用Invoke方法異步更新。以下代碼段實現在子線程中更新Label控件的Text屬性

 

[csharp] view plaincopy
  1. private void button6_Click(object sender, EventArgs e)  
  2. {  
  3.      Thread demoThread =new Thread(new ThreadStart(threadMethod));  
  4.      demoThread.IsBackground = true;  
  5.      demoThread.Start();//啟動線程  
  6. }  
  7.   
  8.  void threadMethod()  
  9.  {   
  10.       Action<String> AsyncUIDelegate=delegate(string n){label1.Text=n;};/<span >/定義一個委托</span>  
  11.       label1.Invoke(AsyncUIDelegate,new object[]{"修改後的label1文本"});  
  12.  }  


2.使用SynchronizationContext的Post/Send方法更新

SynchronizationContext類在System.Threading命令空間下,可提供不帶同步的自由線程上下文,其中Post方法簽名如下:

public virtual void Post(SendOrPostCallback d,Object state)    //將異步消息調度到一個同步上下文

可以看出我們要異步更新UI控件,第一是要獲取UI線程的上下文了,第二就是調用post方法了,代碼實現:

 

[csharp] view plaincopy
    1. SynchronizationContext _syncContext = null;  
    2.   
    3. private void button6_Click(object sender, EventArgs e)  
    4. {  
    5.     Thread demoThread =new Thread(new ThreadStart(threadMethod));  
    6.     demoThread.IsBackground = true;  
    7.     demoThread.Start();//啟動線程  
    8. }  
    9.   
    10. //窗體構造函數     
    11. public Form1()  
    12. {  
    13.     InitializeComponent();  
    14.       //獲取UI線程同步上下文  
    15.     _syncContext = SynchronizationContext.Current;  
    16. }  
    17.   
    18. private void threadMethod()  
    19. {  
    20.      _syncContext.Post(SetLabelText, "修改後的文本");//子線程中通過UI線程上下文更新UI  
    21. }  
    22.    
    23. private void SetLabelText(object text)  
    24. {  
    25.     this.lable1.Text = text.ToString();  

C語言&& || !分別是什

&是取址運算符,作用是提取一個變量的地址。
比如你定義了一個變量,那麼在編譯時,系統就會在內存中分配一個空間。
而這個空間在內存中的位置就是它的地址。&就提取它的地址。
e.g int a;在編譯時就給它分配一個地址,比如是2000;&a就是2000。
假如先定義了一個整型指針變量p,p=&a;就是把a的地址2000賦給p。運行後p=2000。
又如scanf("%d",&a);當你輸入3時,它會先根據&a知道a的地址,由地址找到a在內存中的空間,再把3寫入這個空間。
*是指針運算符,作用與&相反,它是根據變量的地址取出變量的值。
比如,*a的值就是變量a的值3。
下面是定義和聲明中用到指針的小結
int *p; 定義一個指向整型數據的指針。
int *p[n]; 定義指針數組p,它由n個指向整型數據的指針元素組成。
int (*p)[n]; p為指向含n個元素的一維數組的指針變量。
int *p(); p為返回一個指針的函數,該指針指向整型數據。
int (*p)(); p為指向函數的指針,該函數返回一個整型值
int **p; p是一個指針變量,它指向一個指向整型數據的指針變量。
如果你想系統的了解建議你可以看看譚浩強的《c程序設計》(第三版)這本書通俗易懂。是學習c語言不錯的教材。
 

C語言&& || !分別是什

&是取址運算符,作用是提取一個變量的地址。
比如你定義了一個變量,那麼在編譯時,系統就會在內存中分配一個空間。
而這個空間在內存中的位置就是它的地址。&就提取它的地址。
e.g int a;在編譯時就給它分配一個地址,比如是2000;&a就是2000。
假如先定義了一個整型指針變量p,p=&a;就是把a的地址2000賦給p。運行後p=2000。
又如scanf("%d",&a);當你輸入3時,它會先根據&a知道a的地址,由地址找到a在內存中的空間,再把3寫入這個空間。
*是指針運算符,作用與&相反,它是根據變量的地址取出變量的值。
比如,*a的值就是變量a的值3。
下面是定義和聲明中用到指針的小結
int *p; 定義一個指向整型數據的指針。
int *p[n]; 定義指針數組p,它由n個指向整型數據的指針元素組成。
int (*p)[n]; p為指向含n個元素的一維數組的指針變量。
int *p(); p為返回一個指針的函數,該指針指向整型數據。
int (*p)(); p為指向函數的指針,該函數返回一個整型值
int **p; p是一個指針變量,它指向一個指向整型數據的指針變量。
如果你想系統的了解建議你可以看看譚浩強的《c程序設計》(第三版)這本書通俗易懂。是學習c語言不錯的教材。
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved