【问题标题】:How do I query a WPF property from a different thread in C++/CLI?如何从 C++/CLI 中的不同线程查询 WPF 属性?
【发布时间】:2013-07-16 12:52:35
【问题描述】:

我有一段 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' 和 'p' 上有一个轻量级(即不需要太多代码)闭包,作为我可以传递给 Dispatcher::Invoke 的东西。有人知道怎么做吗?

【问题讨论】:

    标签: .net wpf reflection delegates c++-cli


    【解决方案1】:

    类似下面的东西应该可以工作。它使用Func&lt;T1, T1, TResult&gt; 委托来调用静态方法。方法参数被传递给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&lt;Object^, Object^&gt; 委托。不知道它是否是有效的 C++/CLI,但它对我来说很好。

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

    【讨论】:

    • +1:啊,有趣-我不知道Func。我正在尝试消化 Func 构造函数所采用的参数的文档。它只能用于为对象方法创建委托,即不是静态(类)方法吗?我尝试调整您的代码,使其使用纯静态函数Object ^GetValue( Object ^o, PropertyInfo ^p );,然后将gcnew Func&lt;Object ^, PropertyInfo ^, Object ^&gt;( dispObj, propertyInfo, &amp;GetValue ); 传递给Invoke,希望我可以轻松地接近dispObjpropertyInfo,而无需专门的类.. .
    • @JochenKalmbach 这正是我们所要求的。 GetValue 必须在 UI 线程中调用,以避免问题中提到的 TargetInvocationException
    • Clemens,你最后一次甚至不需要静态方法的编辑真是太棒了! :-) 我无法想象它会比这更好,所以我会接受你的回答。
    猜你喜欢
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    相关资源
    最近更新 更多