将事件分派到正确的线程中

时间:2012-11-08 15:56:11

标签: winforms c++-cli event-dispatch-thread

我开发了一个使用回调来通知事件的库的包装器。使用除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类吗?

感谢。

1 个答案:

答案 0 :(得分:1)

是的,这不是正确的方法。 Winforms和WPF有不同的同步提供程序,它们在System :: Threading :: SynchronizationContext :: Current中安装它们。

要使用它,请复制构造函数中的Current值。当您准备发起事件时,请检查它是否为 nullptr 。如果是,那么你的对象是在一个工作线程中构建的,你应该直接激活你的事件。如果不是,则使用Post()方法在UI线程上运行辅助方法。 那个帮助方法会触发事件。