我有一堆控件需要从另一个线程更新。虽然使用Control.Invoke显然可以实现这一点,但对于至少10个控件分配,是否有一种优雅的方法可以做到这一点?
此外,此代码有什么问题?
InstallationStatus.Invoke(myDelegate = new AssignmentDelegate(InstallationStatus));
我想从委托内部设置标签(InstallationStatus)的状态。委托采用Control类型的参数,错误是:
安装是一个字段,但用作方法。
由于
答案 0 :(得分:2)
委托构造函数接受目标方法来调用;也许这里最方便的方法是:
InstallationStatus.Invoke(
(MethodInvoker) delegate { InstallationStatus = blah; });
虽然存在其他变体(将控件作为参数传递给正式方法)
答案 1 :(得分: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实例。 Form的构造函数通常是个好地方。在您传递给Send()方法的委托(或匿名方法)中,您显然可以更新多个控件。
答案 2 :(得分: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
}
}
}
}