2013-04-05 30 views
2

我正在使用線程在我的程序的UI中運行長操作,以便它不鎖定。但是,在這些任務中,我需要更新控件,這不可能來自創建它們的線程。建議使用control.BeginInvoke(Delegate)來執行你想要的方法。C#Control.Invoke方法組

但是,要做到這一點,你必須聲明一個委託類型,然後纔可以調用它們。

因此,它是這樣的:如果我想執行方法無效更新(),我必須去:

delegate void CallbackVoid(); 
void Update() {...} 

...(in task code)... 
this.BeginInvoke(new CallbackVoid(Update)); 

這是相當煩人對於每個單獨的方法做出來那裏。我不能只是以某種方式做到這一點自然,如:

void Update() {...}  
this.BeginInvoke(Update); 

回答

1

修訂作品WPF!

您可以使用匿名方法短的語法,甚至沒有宣佈你的方法,其簡化的東西

Dispatcher.BeginInvoke(DispatcherPriority.Background, new MethodInvoker(() => 
       { 
        //Your Update code 
       })); 
+0

與control.Invoke(新的EventHandler(代表 {/ *更新控制在這裏* /})); ?哪個更好? – Arie 2013-04-05 13:24:24

+0

@Arie兩者都是正確的,但不是其他。 MSDN表示:「委託可以是EventHandler的一個實例,在這種情況下,sender參數將包含此控件,而Event參數將包含EventArgs.Empty。委託也可以是MethodInvoker的實例或任何其他代理一個void參數列表,對EventHandler或MethodInvoker委託的調用將比對另一個委託類型的調用快得多「 – Alex 2013-04-05 13:28:42

+0

@voo:實際上,這個*對於Windows窗體不是正確的,這就是問題的癥結所在... – 2013-04-05 13:41:42

2

一種選擇是添加一個擴展方法:

public static void BeginInvokeAction(this Control control, Action action) 
{ 
    control.BeginInvoke(action); 
} 

然後,你可以使用:

this.BeginInvokeAction(action); 

這個工程的原因是我們是現在爲編譯器提供具體的委託類型以將方法組轉換爲。

0

嘗試以下操作:

if (this.controlname.InvokeRequired && !this.controlname.IsDisposed) 
       { 
        Invoke(new MethodInvoker(delegate() 
         { 
          //Update control on GUI here! 

    })); 
    else if(!this.controlname.IsDisposed) 
    { 
          //AND here! 
    } 
+0

這實際上是*更多*代碼,而不是更少,並且沒有任何其他解決方案的優勢。整個想法是OP *知道*他是而不是在UI線程中;不需要檢查,並且他知道這些控件不會被丟棄(如果不是這樣,它確實會更好,因此您可以找到/修復該錯誤,而不是靜靜地繼續)。 – Servy 2013-04-05 13:37:20

0

BeginInvoke是異步的,Invoke是同步的,你用哪一個取決於你想要做什麼。如果您在繼續之前需要完成呼叫,則需要同步呼叫。

這是我最喜歡的同步所調用的結構:

static void InvokeIfRequired(Control control, Action action) 
{ 
    if (control.InvokeRequired) 
    { 
     control.Invoke(action); 
    } 
    else 
    { 
     action.Invoke(); 
    } 
} 

使用:

void MyTestFunction() 
{ 
    InvokeIfRequired(myControl,() => 
     { 
      MyFunction(); 
      MyOtherFunction(); 
     }); 

    // Or more simply: 
    InvokeIfRequired(myControl,() => MyFunction()); 
} 

有在創建行動的一個小的開銷,但它簡化了代碼頗有幾分不必須考慮到處處的細節。