2015-05-12 12 views
2

我有這個有點令人費解的情況。 我給了一個對象o,字符串n和對象數組args。我將用給定的參數在對象o上調用方法n尋找正確的線程來調用一個沒有失敗的方法

問題是這個輸入總是來自同一個線程,並且提供的對象是(有時)在不同線程上創建的控件。所以當我嘗試調用它們的某些方法時,我得到了跨線程調用異常。

這不會是一個問題,如果我可以檢查對象是否是一個控件,然後調用它的方法並在該調用中執行我的操作。不幸的是,我不能這樣做,因爲我可以通過一個屬於某個控件的ControlCollection對象。如果我將其稱爲Add方法,我會得到例外,但ControlCollection沒有Invoke方法。

我該怎麼辦?性能不是我擔心的事情,所以任何解決方案都是不錯的。也許如果我可以捕獲異常並獲得它想讓我調用的線程,那麼重複該調用?或者也許有一種方法來獲得線程對象「屬於」?

+0

'提供的對象(有時)是在不同的線程上創建的控件 - 只是100%清晰 - 你不僅在UI線程中創建控件,而且在其他線程中創建控件? – anikiforov

+0

@anikiforov嗯...現在你提到它,我是,但那可能不是我想要做的,是吧?我可以在同一個線程上創建多個表單並讓它們同時運行嗎?因爲目前我正在爲每個表單創建一個新線程。也許是 –

+0

。我得到的是 - 如果你的所有控件都是在單一的(UI)線程上創建的 - 你可能會通過檢查「InvokeRequired」,然後在一些已知的Control對象上調用「Invoke」檢查'InvokeRequired'。如果你可以以某種方式在你的方法中獲得對該實例的引用,那就是。 – anikiforov

回答

3

你能這樣做嗎?概括這個

Action action =() => o.GetType().GetMethod(n).Invoke(o, args); 

if (o is Control) 
{ 
    var c = o as Control; 
    c.Invoke(action); 
} 
else if (o is ControlCollection) 
{ 
    var c = (o as ControlCollection).Owner; 
    c.Invoke(action); 
} 
else 
{ 
    action(); 
} 

一種方法是這樣來做:

 Action action =() => o.GetType().GetMethod(n).Invoke(o, args); 

     var controlMaps = new Func<object, Control>[] 
     { 
      x => x as Control, 
      x => o is ControlCollection ? (o as ControlCollection).Owner : null, 
     }; 

     var c = controlMaps 
       .Select(m => m(o)) 
       .Where(x => x != null) 
       .FirstOrDefault(); 

     if (c != null) 
     { 
      c.Invoke(action); 
     } 
     else 
     { 
      action(); 
     } 

然後,如果你有很多不同的對象類型,你可以創建controlMaps陣列中的映射。

+0

這會工作,但我一直在尋找一種通用的方法。 –

+0

@LukaHorvat - 推廣這一點不會太繁重。 – Enigmativity

+0

這將是如果你想映射整個System.Windows.Forms命名空間。 –

相關問題