C#Invoke委託在多執行緒中的使用
一步一步跟隨著我的腳步看一看
Form上我設定一個button,text屬性為“點選開始測試”;現在我想點選它以後,動態變化從1~10賦值
(1)
第一個映入腦中的方式就是這樣寫
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
for(int i=1;i<10;i++)
{
button1.Text = i.ToString();
Thread.Sleep(1000);
}
button1.Text = "點選開始測試";
button1.Enabled = true;
}
有沒有問題?肯定有的啦,我點選以後,介面倒是disable了,但是沒有1~10出現,時間一到,恢復enable。為什麼呢?
原因:直接主執行緒休眠是達不到效果的,此時桌面還處於假死狀態,更新不了text值。程式碼放在了UI執行緒執行,阻塞了UI的顯示,所以中間的結果你看不到。實驗了兩種方式解決:
- 在Thread.Sleep(1000);後加 button1.Refresh();
- 在Thread.Sleep(1000);後加 Application.DoEvents();
(2)
既然是由於程式碼放在了UI執行緒,那我新建個執行緒,在那裡面更新UI控制元件好了。
private void button1_Click(object sender, EventArgs e)
{
//啟動一個執行緒
new Thread(ThreadTask).Start();
}
//執行緒函式
public void ThreadTask()
{
button1.Enabled = false;
for (int i = 0; i < 10; i++)
{
button1.Text = i.ToString();
Thread.Sleep(1000);
}
button1.Text = "點選開始測試";
button1.Enabled = true;
}
出錯了!!!
造成這種異常的原因在於,控制元件是在主執行緒中建立的(比如this.Controls.Add(...);),進入控制元件的事件響應函式時,是在控制元件所在的執行緒,並不是主執行緒。在控制元件的事件響應函式中改變控制元件的狀態,可能與主執行緒發生執行緒衝突。如果主執行緒正在重繪控制元件外觀,此時在別的執行緒改變控制元件外觀,就會造成畫面混亂。
(3)
下面該主角出場了,C#的委託機制,由於歷史的原因,有這麼幾種形式:
//第一種
button1.Invoke(new EventHandler(delegate{button1.Text = "關閉";}));
//第二種
this.Invoke(new EventHandler(delegate{button1.Text = "關閉";}));
//第三種 網上說自C# 3.0開始就有了
this.Invoke(new Action(() =>{ button1.Text = "關閉";}));
我喜歡用第三種,好記,哈哈。好了,接下來實現以下吧!
private void button1_Click(object sender, EventArgs e)
{
//啟動一個執行緒
new Thread(ThreadTask).Start();
}
//執行緒函式
public void ThreadTask()
{
//首先將button物件禁用
this.Invoke(new Action(() =>
{
button1.Enabled = false;
}));
for (int i = 0; i < 10; i++)
{
this.Invoke(new Action(() =>
{
button1.Text = i.ToString();
}));
Thread.Sleep(1000);
}
//雖然不是迴圈內,請不要忘記,你的呼叫依然在輔助執行緒中,所以,還是需要invoke的。
//還原狀態,設定按鈕的文字為初始狀態,設定按鈕可用。
this.Invoke(new Action(() =>
{
button1.Text = "點選開始測試";
button1.Enabled = true;
}));
}
大功告成嘍!!
相關文章
- 使用委託開啟多執行緒(多執行緒深入)執行緒
- 子執行緒與UI執行緒的通訊(委託)執行緒UI
- ios中的多播委託iOS
- Java多執行緒-執行緒池的使用Java執行緒
- java多執行緒之執行緒的基本使用Java執行緒
- Java中的多執行緒Java執行緒
- Spring中多執行緒的使用及問題Spring執行緒
- 多執行緒的libcurl的使用執行緒
- PyQt應用程式中的多執行緒:使用Qt還是Python執行緒?QT執行緒Python
- Android中的多程式、多執行緒Android執行緒
- Python中的多工:多執行緒Python執行緒
- java使用多執行緒Java執行緒
- iOS多執行緒全套:執行緒生命週期,多執行緒的四種解決方案,執行緒安全問題,GCD的使用,NSOperation的使用iOS執行緒GC
- Java多執行緒的使用(二)Java執行緒
- python多執行緒中:如何關閉執行緒?Python執行緒
- Java中多執行緒的案例Java執行緒
- 多執行緒和多執行緒同步執行緒
- 多執行緒程式設計基礎(一)-- 執行緒的使用執行緒程式設計
- 多執行緒在微服務API統計和健康檢查中的使用執行緒微服務API
- JSRE中的多工與多執行緒JS執行緒
- 多執行緒:執行緒池理解和使用總結執行緒
- 執行緒以及多執行緒,多程式的選擇執行緒
- 多執行緒--執行緒管理執行緒
- 執行緒與多執行緒執行緒
- 多執行緒【執行緒池】執行緒
- @Async使用ThreadPoolTaskExecutor 多執行緒thread執行緒
- Swift多執行緒:使用Thread進行多執行緒間通訊,協調子執行緒任務Swift執行緒thread
- Java多執行緒——synchronized的使用示例Java執行緒synchronized
- 行為委託
- 執行緒和程式基礎以及多執行緒的基本使用(iOS)執行緒iOS
- java 多執行緒之使用 interrupt 停止執行緒的幾種方法Java執行緒
- 多執行緒程式設計基礎(二)-- 執行緒池的使用執行緒程式設計
- 多執行緒(五)---執行緒的Yield方法執行緒
- 【Java多執行緒】執行緒安全的集合Java執行緒
- Java中一個物件在多執行緒中是共享的Java物件執行緒
- springboot配置執行緒池使用多執行緒插入資料Spring Boot執行緒
- Qt中的多執行緒與執行緒池淺析+例項QT執行緒
- Java中的多執行緒詳解Java執行緒