2011-05-05 54 views
2

我有一堆需要從另一個線程更新的控件。雖然通過使用Control.Invoke這顯然是可能的,但有沒有一種優雅的方式來做到這一點至少10控制任務?Control.Invoke問題(x是一個字段,但像方法一樣使用)

另外,這段代碼有什麼問題?

InstallationStatus.Invoke(myDelegate = new AssignmentDelegate(InstallationStatus)); 

我想從代理內部設置標籤(InstallationStatus)的狀態。代表需要Control類型的參數,錯誤是:

安裝是一個字段,但用法類似於方法。

由於

+0

沒有'Installation'在你的榜樣,所以我們真的不能評論「安裝是一個領域,但採用類似的方法。」 – 2011-05-05 22:44:47

回答

2

委託構造接受目標方法來調用;也許是這裏最方便的方法是:

InstallationStatus.Invoke(
     (MethodInvoker) delegate { InstallationStatus = blah; }); 

雖然其他變種,(通過控制作爲參數傳遞給一個正式的方法)

+0

這很完美,謝謝! – dotnetdev 2011-05-05 23:10:27

0

的替代方案(恕我直言語法有點更吸引人),這樣做的方式是通過SynchronizationContext.Send()它可以這樣使用:

private System.Threading.SynchronizationContext syncContext; 

public Form1() 
{ 
    InitializeComponent(); 
    syncContext = System.Threading.SynchronizationContext.Current; 
} 

private void UpdateControlsOnTheUIThread() 
{ 
    syncContext.Send(x => 
    { 
     // Do sth here.. 
     myControl.Property = newValue; 
    }, null); 
} 

重要的是在合適的時間來檢索(和存儲)的SynchronizationContext實例。表單的構造函數通常是一個好地方。在傳遞給Send()方法的委託(或匿名方法)中,顯然可以更新多個控件。

0

這裏我創建了一個示例小Windows窗體應用程序,演示如何在運行時使用反射動態設置屬性。乾淨地做這件事的好方法可能是迭代通過某種集合類型。

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 
    private void Form1_Load(object sender, EventArgs e) 
    { 
     //This sample shows invocation using a loosely typed object. 
     //Assumes you will send the correct object type to the property setter at runtime 
     Dictionary<string, object> setupObjectValues = new Dictionary<string, object>(); 
     setupObjectValues.Add("Text", "Hello World"); 
     setupObjectValues.Add("ReadOnly", true); 
     setupObjectValues.Add("Location", new Point(10, 5)); 
     foreach (string val in setupObjectValues.Keys) 
     { 
      UpdateControlObjectValue(textBox1, val, setupObjectValues[val]); 
     } 
    } 
    public delegate void SetObjectPropertyDelegate(Control param, string PropertyName, object NewValue); 
    public void UpdateControlObjectValue(Control sender, string PropertyName, object Value) 
    { 
     //Pass the method name into the delegate and match signatures 
     //params collection used for parameters on method called in this case object and string 
     sender.Invoke(new SetObjectPropertyDelegate(SetObjectProperty), sender, PropertyName, Value); 
    } 
    //Called by delegate (Matches signature of SetObjectPropertyDelegate) 
    private void SetObjectProperty(Control sender, string PropertyName, object NewValue) 
    { 
     if (sender == null || String.IsNullOrEmpty(PropertyName) || NewValue == null) 
      throw new ArgumentException("Invalid Argument"); 
     try 
     { 
      //Guaranteed to be a control due to strong typing on parameter declaration 
      sender.GetType().GetProperty(PropertyName).SetValue(sender, NewValue, null); 
      //Set Value on MSDN doc : http://msdn.microsoft.com/en-us/library/xb5dd1f1.aspx 
     } 
     catch (System.Reflection.AmbiguousMatchException ex) 
     { 
      //Two properties were found that match your Property Name 
     } 
     catch (ArgumentNullException ex) 
     { 
      //Null Property Found 
     } 
     catch (ArgumentException ex) 
     { 
      //Invalid Argument 
     } 
     catch (System.Reflection.TargetException ex) 
     { 
      //Invalid Target 
     } 
     catch (System.Reflection.TargetParameterCountException ex) 
     { 
      //Invalid number of parameters passed to reflection invoker 
     } 
     catch (System.MethodAccessException ex) 
     { 
      //Could not access the method to invoke it 
     } 
     catch (System.Reflection.TargetInvocationException ex) 
     { 
      //Problem invoking the target method 
     } 
     catch (Exception ex) 
     { 
      //serious problem 
     } 
    } 
} 

}

相關問題