我有一段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的东西。有人知道怎么做吗?
答案 0 :(得分:1)
以下内容应该有效。它使用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);
}
};
以下代码根本不需要静态方法。它直接从Func<Object^, Object^>
实例和PropertyInfo
方法创建PropertyInfo::GetValue
委托。不知道它是否是有效的C ++ / CLI,但它对我来说很好。
Object^ result = dispObj->Dispatcher->Invoke(
gcnew Func<Object^, Object^>(propertyInfo, &PropertyInfo::GetValue), dispObj);