我开发了一个使用回调来通知事件的库的包装器。使用除UI线程之外的其他线程调用此回调,因此包装器使用以下脚本将事件处理程序调用到WinForm应用程序的正确线程中。
void AoComm::Utiles::Managed::DispatchEvent( Delegate^ ev, Object^ sender, Object^ args )
{
ComponentModel::ISynchronizeInvoke^ si;
array<Delegate^>^ handlers;
if(ev != nullptr)
{
handlers= ev->GetInvocationList();
for(int i = 0; i < handlers->Length; ++i)
{
// target implements ISynchronizeInvoke?
si = dynamic_cast<ComponentModel::ISynchronizeInvoke^>(handlers[i]->Target);
try{
if(si != nullptr && si->InvokeRequired)
{
IAsyncResult^ res = si->BeginInvoke(handlers[i], gcnew array<Object^>{sender, args});
si->EndInvoke(res);
}else{
Delegate^ del = handlers[i];
del->Method->Invoke( del->Target, gcnew array<Object^>{sender, args} );
}
}catch(System::Reflection::TargetException^ e){
Exception^ innerException;
if (e->InnerException != nullptr)
{
innerException = e->InnerException;
}else{
innerException = e;
}
Threading::ThreadStart^ savestack = (Threading::ThreadStart^) Delegate::CreateDelegate(Threading::ThreadStart::typeid, innerException, "InternalPreserveStackTrace", false, false);
if(savestack != nullptr) savestack();
throw innerException;// -- now we can re-throw without trashing the stack
}
}
}
}
这段代码工作得很好,但我读过WPF的Dispatcher类,它和我的代码一样(当然还有更多)。 那么,有什么东西(类,机制,......)等同于WinForms的Dispatcher类吗?
感谢。
答案 0 :(得分:1)
是的,这不是正确的方法。 Winforms和WPF有不同的同步提供程序,它们在System :: Threading :: SynchronizationContext :: Current中安装它们。
要使用它,请复制构造函数中的Current值。当您准备发起事件时,请检查它是否为 nullptr 。如果是,那么你的对象是在一个工作线程中构建的,你应该直接激活你的事件。如果不是,则使用Post()方法在UI线程上运行辅助方法。 那个帮助方法会触发事件。