0

我为使用回调通知事件的库开发了一个包装器。此回调是使用 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 类等效的东西(类、机制……)?

谢谢。

4

1 回答 1

3

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

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

于 2012-11-08T19:01:37.560 回答