Control.Invoke问题(x是一个字段,但像方法一样使用)

时间:2011-05-05 22:36:42

标签: c#

我有一堆控件需要从另一个线程更新。虽然使用Control.Invoke显然可以实现这一点,但对于至少10个控件分配,是否有一种优雅的方法可以做到这一点?

此外,此代码有什么问题?

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

我想从委托内部设置标签(InstallationStatus)的状态。委托采用Control类型的参数,错误是:

安装是一个字段,但用作方法。

由于

3 个答案:

答案 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
        }
    }
}

}