如何在C++/CLI中从不同的线程查询WPF属性



我有一段C++/CLI代码,它使用反射API查询一些WPF控件的属性值,如下所示:

Type ^t = ...;
Object ^o = ...;
PropertyInfo ^p = t->GetProperty( "Enabled" );
Object ^v = p->GetValue( o, nullptr );

这运行得很好,但现在我不得不将这些代码移到一个单独的线程中。这样做使得最后一次GetValue调用产生了关于禁止从不同线程访问对象的异常。

知道我的WPF控件是DispatcherObjects,我知道我可以对它们使用Invoke(),并传递一个Action,使一段代码在与目标对象相同的线程中执行。但是,我不知道如何在C++/CLI中做到这一点。特别是,我如何传递函数(即接受参数并返回值的函数)?

理想情况下,我可以做一些类似的事情

// Toplevel code:
delegate Object ^GetPropertyDelegate( Object ^o, PropertyInfo ^p );
// Then, at the place where I perform the GetValue() call:
struct Local {
    static Object ^run( Object ^o, PropertyInfo ^p ) {
        return p->GetValue( o, nullptr );
    }
};
Type ^t = ...;
Object ^o = ...;
PropertyInfo ^p = t->GetProperty( "Enabled" );
DispatcherObject ^dispObj = dynamic_cast<DispatcherObject ^>( o );
Object ^v = dispObj->Dispatcher->Invoke( gcnew GetPropertyDelegate( &Local::run ) );

从技术上讲,这是可编译的,但没有意义。理想情况下,我希望在"o"one_answers"p"上有一个轻量级(即不需要太多代码)闭包,作为可以传递给Dispatcher::Invoke的东西。有人知道怎么做吗?

以下内容应该可以工作。它使用Func<T1, T1, TResult>委托来调用静态方法。方法参数被传递给Dispatcher.Invoke调用。

public ref class YourClass
{
private:
    static Object^ GetValue(Object^ queryObject, PropertyInfo^ queryProperty)
    {
        return queryProperty->GetValue(queryObject);
    }
public:
    static Object^ GetPropertyValue(
        DispatcherObject^ dispObj, PropertyInfo^ propertyInfo)
    {
        return dispObj->Dispatcher->Invoke(
            gcnew Func<Object^, PropertyInfo^, Object^>(&YourClass::GetValue),
            dispObj, propertyInfo);
    }
};

下面的代码甚至根本不需要静态方法。它直接从PropertyInfo实例和PropertyInfo::GetValue方法创建一个Func<Object^, Object^>委托。不知道它是否是有效的C++/CLI,但它对我来说很好。

Object^ result = dispObj->Dispatcher->Invoke(
    gcnew Func<Object^, Object^>(propertyInfo, &PropertyInfo::GetValue), dispObj);

最新更新