Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[心得] delegate();之心得

94 views
Skip to first unread message

我愛秋愛我

unread,
Dec 19, 2008, 4:41:55 PM12/19/08
to
小弟是c#愛用者

在開發過程中,往往參雜著多個執行緒在使用

我從VS 1.1開始用到現在也只停留在2.0階段

沒有想使用3.5的慾望@@

因為小弟是從java陣營跳槽支持c#的(真他媽的好丫)

我相信在執行緒中操作控制項上的內容一定死一堆人

一定常出現這種狀況
=============================================
System.InvalidOperationException 未處理

跨執行緒作業無效: 存取控制項 'tbStatus'

時所使用的執行緒與建立控制項的執行緒不同。"
==============================================

看到這個就相當的火大, 明明在vs 1.1中根本就沒事

原本的程式換到了2.0上就死掉了

更何況又是很急很急的專案呢~

後來去拜見辜狗大神,原來只要加上這個就沒事了

Control.CheckForIllegalCrossThreadCalls=false; (方法一)

真的很討厭,在java也都沒事,在2.0上就死掉

後來開發到後期,對工具的使用也熟悉到一個階段了

開始嘗試比較正規的作法,就是委派事件delegate

=============================================
//(1).設定好委派事件
private delegate void ControlDelegate(string id,object obj);

//(2).設定好讓Thread要叫用的方法
public SetStatus(string id,object obj){
this.invoke(new ContrlDelegate(this.SetStatusDelegate),
new object[]{id,obj});
}
//(3).真正執行方法的地方
private SetStatusDelegate(string id,object obj){
if(id.Equals("Message")){
this.label1.Text = (string)obj;
}
else if(id.Equals("FileInfo")){
FileInfo info = (FileInfo)obj;
}
}

到時候我只要在Thread中,透過SetStatus("Message","Starlife是帥哥");
就ok了
=============================================

這個方法是自己領悟出來的,真神奇有這種方法

無法是從Socket哪丟來的訊息,或是從硬体設備丟出來的訊息

都可以透過SetStatus的方式去使用,個人蠻prefer這種正規做法

不過寫到後面真的會想偷懶,因為要一直去定義一堆有的沒有的id

很煩的,於是開始愛上匿名方法,也就是

============================================
private delegate void ControlDelegate();
this.invoke(new ControlDelegate(delegate(){
//Do Something
}));

又簡短又有力
============================================

打完收功,以上只是小弟的小小心得

如果有更好的方法,也請諸位大大能不吝請教指點一番

(好吧我承認我來賺文章數和p幣的)

--
我很可憐,前幾天出了場車禍,
對方一下車不清青紅皂白的就把我打了一頓,
我問他為什麼打我?他說因為我長的太帥,我很生氣!!
因為我覺得我長的一點都不出色...
我抓了個路人來幫我評評理,那路人也打了我一頓,�為他說我說謊..我招誰惹誰了我!!

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 163.17.9.234

子凌(b)

unread,
Dec 20, 2008, 5:43:59 AM12/20/08
to
※ 引述《starlife672 (我愛秋愛我)》之銘言:
: Control.CheckForIllegalCrossThreadCalls=false; (方法一)
這不是好作法,因為當發生問題時,怎麼死的都不知道

如果是經常性使用到的方法,例如幾秒鐘就會呼叫一次的話
建議建立一個實體 Delegate 來呼叫,而不是一直產生暱名 Delegate
我直接改在下面
: //(1).設定好委派事件


: private delegate void ControlDelegate(string id,object obj);

private ControlDelegate _setStatusDelegate; // 宣告 Delegate 實體

public static void Main(string[] args) // 或是 Form_Load
{
_setStatusDelegate = new ContrlDelegate(this.SetStatusDelegate);
........
}

: //(2).設定好讓Thread要叫用的方法


: public SetStatus(string id,object obj){
: this.invoke(new ContrlDelegate(this.SetStatusDelegate),
: new object[]{id,obj});

改成 this.invoke(_setStatusDelegate, id, obj);

另外 invoke 方法的第二參數是 params object[]
所以不需要 new object[]
詳細請見 params 關鍵字的說明

: //(3).真正執行方法的地方


: private SetStatusDelegate(string id,object obj){
: if(id.Equals("Message")){
: this.label1.Text = (string)obj;
: }
: else if(id.Equals("FileInfo")){
: FileInfo info = (FileInfo)obj;
: }
: }
: 到時候我只要在Thread中,透過SetStatus("Message","Starlife是帥哥");
: 就ok了

--
my blog: http://kenshinnn.blogspot.com
operation system : Ubuntu GNU/linux
window manager : Gnome

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.117.167.161

wvsrugby

unread,
Dec 20, 2008, 1:25:01 PM12/20/08
to
MSDN 中有絕妙的範例,
先判斷 Control.InvokeRequired,
再決定是否需要去 invoke delegate,
不然只是浪費系統資源.

public void UpdateStatus(object obj)
{
if (this.InvokeRequired)
{
this.Invoke(new Action<object>(UpdateStatus), obj);
return;
}

FileInfo fileInfo = obj as FileInfo;
if (fileInfo != null)
{
//...
return;
}

this.label1.Text = obj.ToString();
}

※ 引述《starlife672 (我愛秋愛我)》之銘言:
: 小弟是c#愛用者


: 在開發過程中,往往參雜著多個執行緒在使用
: 我從VS 1.1開始用到現在也只停留在2.0階段
: 沒有想使用3.5的慾望@@
: 因為小弟是從java陣營跳槽支持c#的(真他媽的好丫)
: 我相信在執行緒中操作控制項上的內容一定死一堆人
: 一定常出現這種狀況
: =============================================
: System.InvalidOperationException 未處理
: 跨執行緒作業無效: 存取控制項 'tbStatus'
: 時所使用的執行緒與建立控制項的執行緒不同。"
: ==============================================
: 看到這個就相當的火大, 明明在vs 1.1中根本就沒事
: 原本的程式換到了2.0上就死掉了
: 更何況又是很急很急的專案呢~
: 後來去拜見辜狗大神,原來只要加上這個就沒事了
: Control.CheckForIllegalCrossThreadCalls=false; (方法一)
: 真的很討厭,在java也都沒事,在2.0上就死掉
: 後來開發到後期,對工具的使用也熟悉到一個階段了
: 開始嘗試比較正規的作法,就是委派事件delegate
: =============================================

: //(1).設定好委派事件
: private delegate void ControlDelegate(string id,object obj);

: //(2).設定好讓Thread要叫用的方法
: public SetStatus(string id,object obj){
: this.invoke(new ContrlDelegate(this.SetStatusDelegate),
: new object[]{id,obj});

: }


: //(3).真正執行方法的地方
: private SetStatusDelegate(string id,object obj){
: if(id.Equals("Message")){
: this.label1.Text = (string)obj;
: }
: else if(id.Equals("FileInfo")){
: FileInfo info = (FileInfo)obj;
: }
: }
: 到時候我只要在Thread中,透過SetStatus("Message","Starlife是帥哥");
: 就ok了

: =============================================


: 這個方法是自己領悟出來的,真神奇有這種方法
: 無法是從Socket哪丟來的訊息,或是從硬体設備丟出來的訊息
: 都可以透過SetStatus的方式去使用,個人蠻prefer這種正規做法
: 不過寫到後面真的會想偷懶,因為要一直去定義一堆有的沒有的id
: 很煩的,於是開始愛上匿名方法,也就是
: ============================================
: private delegate void ControlDelegate();
: this.invoke(new ControlDelegate(delegate(){
: //Do Something
: }));
: 又簡短又有力
: ============================================
: 打完收功,以上只是小弟的小小心得
: 如果有更好的方法,也請諸位大大能不吝請教指點一番
: (好吧我承認我來賺文章數和p幣的)

--

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 218.161.33.38

0 new messages