找到正确的线程来调用方法而不会失败

时间:2015-05-12 20:42:16

标签: c# multithreading winforms reflection

我有这种有点复杂的情况。 我给了一个对象o,一个字符串n和一个对象数组args。我将使用给定的参数调用对象n上的方法o

问题是这个输入总是来到同一个线程,并且提供的对象是(有时)在不同线程上创建的控件。所以当我尝试在它们上调用某些方法时,我得到了跨线程调用异常。

如果我可以检查对象是否是一个控件,然后调用它的Invoke方法并在该调用中执行我的操作,那将不会有问题。不幸的是,我不能这样做,因为我可以传递一个属于某个控件的ControlCollection对象。如果我将其称为Add方法,则会收到异常,但ControlCollection没有Invoke方法。

我该怎么办?性能不是我所担心的,所以任何解决方案都是好的。也许如果我能捕获异常并获得它想要的线程,那么重复调用?或者也许有一些方法可以让线程成为“属于”的对象?

1 个答案:

答案 0 :(得分: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数组中创建一个映射。