2011-05-05 48 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 
     } 
    } 
} 

}

相关问题