在C#中,一般情況下,控制GUI元件時,必須要用main thread去控制。然而我們常常將運算丟至一個新的thread中,然後在運算時更新GUI的狀態。這時例外就會警告你不能這樣做。MSDN提供了delegate解法去做,但我覺得麻煩,也不夠直覺。後來參考了這裡,是使用SynchronizationContext,發現還挺好用的。使用方如下。
首先在GUI class範疇下宣告SynchronizationContext。
public partial class A:Form{
SynchronizationContext mainSynchronizationContext;
}
SynchronizationContext mainSynchronizationContext;
}
接著在constructor上面,將SynchronizationContext做指定。這樣SynchronizationContext就可以抓得到現在的執行緒。
public partial class A:Form{
public A(){
mainSynchronizationContext = SynchronizationContext.Current;
}
}
public A(){
mainSynchronizationContext = SynchronizationContext.Current;
}
}
然後寫一個方法,負責執行GUI更新動作。label1在這裡是一個Lebel類別
public void InvokeGUI(string str) {
mainSynchronizationContext.Post
(
new SendOrPostCallback
(
(obj)
=>
{
label1.Text=(String)obj;
}
)
,
str
);
}
mainSynchronizationContext.Post
(
new SendOrPostCallback
(
(obj)
=>
{
label1.Text=(String)obj;
}
)
,
str
);
}
其中mainSynchronizationContext.Post,是非同步處理,指的是不會等待GUI就進行下一步驟。如果使用mainSynchronizationContext.Send的話,則是進行同步處理。當GUI真正動作完成才會做返回動作。script則是傳入的引數。
然後在你的thread運算時呼叫這個function,便不會拋出例外訊息了。
參考資料:
[1] (筆記) 跨執行緒存取控制項 (WPF、WinForm 通用)
[2] 深入线程,实现自定义的SynchronizationContext
第[2]有詳細說明SynchronizationContext的原理,推薦可以看看。
沒有留言:
張貼留言