2012-10-15 40 views
1

我不是很擅長代表,我不知道發生了什麼。訪問來自其他線程的UI項目時,出現cross thread operation錯誤。避免交叉線程操作錯誤的最簡潔正確的方法?

我想要做的是在Utility類中編寫一個通用函數,以便我可以將任何方法/代碼塊傳遞給該函數。我可以像許多方面:

  1. delegate void UpdateGui(Control c, Action action); 
    public static void Do(Control c, Action action) 
    { 
        try 
        { 
         if (c.InvokeRequired) 
         { 
          UpdateGui updaterdelegate = new UpdateGui(Do); 
          c.TopLevelControl.Invoke(updaterdelegate, new object[] { c, action }); 
         } 
         else 
          action(); 
        } 
        catch (Exception ex) 
        { 
         //throw ex; 
        } 
    } 
    
  2. public static void Do(Control c, Action action) 
    { 
        try 
        { 
         if (c.InvokeRequired) 
         { 
          c.TopLevelControl.Invoke((Action)delegate { Do(c, action); }); 
         } 
         else 
          action(); 
        } 
        catch (Exception ex) 
        { 
         //throw ex; 
        } 
    } 
    
  3. public static void Do(Control c, Action action) 
    { 
        try 
        { 
         if (c.InvokeRequired) 
         { 
          c.TopLevelControl.Invoke(action); 
         } 
         else 
          action(); 
        } 
        catch (Exception ex) 
        { 
         //throw ex; 
        } 
    } 
    
  4. public static void Do(Control c, Action action) 
    { 
        try 
        { 
         if (c.InvokeRequired) 
         { 
          c.TopLevelControl.Invoke(new MethodInvoker(() => action())); 
         } 
         else 
          action(); 
        } 
        catch (Exception ex) 
        { 
         //throw ex; 
        } 
    } 
    
  5. public static void Do(Control c, Action action) 
    { 
        try 
        { 
         if (c.InvokeRequired) 
         { 
          c.TopLevelControl.Invoke(new MethodInvoker(delegate { action(); })); 
         } 
         else 
          action(); 
        } 
        catch (Exception ex) 
        { 
         //throw ex; 
        } 
    } 
    
  6. public static void Do(Control c, Action action) 
    { 
        try 
        { 
         if (c.InvokeRequired) 
         { 
          c.TopLevelControl.Invoke((MethodInvoker)delegate { action(); }); 
         } 
         else 
          action(); 
        } 
        catch (Exception ex) 
        { 
         //throw ex; 
        } 
    } 
    

我相信AP步驟1和2本質上是相同的,並且4,5和6也是如此。我的問題是:

  1. 什麼方法(1 & 2)之間的區別3和(4,5 & 6)?我的意思是,一個人處理/照顧其他人不會處理的情況是什麼?

  2. 什麼是避免cross thread operation錯誤的正確方法,從它的意義上來說,它處理所有的情況,最好是簡潔和可讀?

回答

3

你的「第三」以上(只使用Action)的方法更簡單,更高效。您使用delegate的其他方法會創建一個單獨的方法(通過delegate關鍵字的匿名方法),然後調用您的原始代理(action參數),這是不必要的。

第三個選項只是直接使用Action傳入,這更簡單。

第一個選項類似,但在這種情況下,您傳入的值不是必需的(Control),必須定義自定義委託(儘管您可以使用Action<Control,Action>代替)。由於沒有使用控制,所以沒有理由增加這種複雜性。

在一個側面說明 - 當您在異常處理程序中重新拋出,它會更好只使用throw;(而不是throw ex;),因爲這將保持正確的堆棧跟蹤:

catch (Exception ex) 
{ 
    // Do whatever, ie: logging 
    throw; 
} 

如果您我不打算記錄,只是打算重新拋出,你完全可以忽略try/catch

+0

我更加困惑於'MethodInvoker' ..它代替'delegate','action','()=>'關鍵字做什麼特別的事情? – nawfal

+1

@nawfal這只是另一個委託聲明。實際上,這與使用「操作」相同。 '=>'語法是一個lambda表達式,它是創建匿名方法的新語法(類似於'delegate {}',但語法更清晰)。 –