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

Winforms 将事件分派到正确的线程,winforms,c++-cli,event-dispatch-thread,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;

我为一个库开发了一个包装器,它使用回调来通知事件。此回调是使用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
        }
    }
    }
}
void AoComm::Utiles::Managed::DispatchEvent(委托^ev、对象^sender、对象^args)
{
ComponentModel::ISynchronizeInvoke^si;
数组^处理程序;
如果(ev!=nullptr)
{
handlers=ev->GetInvocationList();
对于(int i=0;iLength;++i)
{
//目标实现ISynchronizeInvoke?
si=动态_cast(处理程序[i]->Target);
试一试{
if(si!=nullptr&&si->invokererequired)
{
IAsyncResult ^res=si->BeginInvoke(处理程序[i],gcnew数组{sender,args});
si->EndInvoke(res);
}否则{
委托^del=handlers[i];
del->Method->Invoke(del->Target,gcnew数组{sender,args});
}
}捕获(系统::反射::目标异常^e){
异常^内部异常;
如果(e->InnerException!=nullptr)
{
innerException=e->innerException;
}否则{
innerException=e;
}
Threading::ThreadStart^savestack=(Threading::ThreadStart^)委托::CreateDelegate(Threading::ThreadStart::typeid,innerException,“InternalPreserveStackTrace”,false,false);
如果(savestack!=nullptr)savestack();
抛出innerException;//--现在我们可以在不破坏堆栈的情况下重新抛出
}
}
}
}
这段代码运行得很好,但我已经阅读了WPF的Dispatcher类,它的功能与我的代码相同(当然还有更多)。 那么,对于WinForms是否有与Dispatcher类等价的东西(类、机制等)


谢谢。

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


要使用它,请复制构造函数中的当前值。准备触发事件时,请检查它是否为nullptr。如果是这样,那么您的对象在工作线程中构造,您应该直接触发事件。如果不是,则使用Post()方法在UI线程上运行帮助器方法。让助手方法触发事件。

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


要使用它,请复制构造函数中的当前值。准备触发事件时,请检查它是否为nullptr。如果是这样,那么您的对象在工作线程中构造,您应该直接触发事件。如果不是,则使用Post()方法在UI线程上运行帮助器方法。让该助手方法触发事件。

谢谢您提供的信息。SynchronizationContext似乎是一种明智的方式。感谢您提供的信息。SynchronizationContext似乎是一种明智的方法。