2016-06-10 12 views
-1

Ich habe eine verwaltete C++ - Anwendung entwickelt, die ein Objekt ManagedSubscription an C# -Clients zurückgibt.
ManagedSubscription empfängt einen Rückruf von C# -Clients, erstellt intern einen eigenen Rückruf, um mit nativem C++ - Code zu kommunizieren.
Beim Überschreiten der Grenzen von nativ zu verwaltet, beobachte ich einen Absturz.
Ich habe try-catch in nativen sowie verwalteten Callbacks, aber es ist nicht gefangen.CrossContext-Ausnahme bei systemeigener zu verwalteter Grenze

Das ist mein Managed C++ Code:

struct NativeCallbackWrapper 
     { 
     public: 
     typedef std::function<bool(const std::vector<Sample>&, bool)> Callback_t; 
     typedef bool(*CallbackPtr)(const std::vector<Sample>&, bool); 

     NativeCallbackWrapper(Callback_t callback) 
      : m_callback(callback) 
     { 
     } 

     ~NativeCallbackWrapper() 
     { 
     } 

     const Callback_t           m_callback; 
     }; 


     //Here is decalred variables in ManagedSubscription.h file 
     typedef std::function<bool(const std::vector<DFS::Chart::Misc::Sample>&, bool)> Callback_t; 
     typedef bool(*CallbackPtr)(const std::vector<DFS::Chart::Misc::Sample>&, bool); 
     delegate bool DelegateFunc(const std::vector<DFS::Chart::Misc::Sample>&, bool); 

     NativeCallbackWrapper      *m_nativeCallbackWrapper; 
     System::Action<TradeResponse, bool>^   m_callback; 
     DelegateFunc^        m_delegate; 
     System::Runtime::InteropServices::GCHandle m_delegateHandle; 


     //This object is returned to C# application 
     ManagedSubscription::ManagedSubscription(
     Action<BidAskResponse, bool>^ callback) 
     { 
     m_delegate = gcnew DelegateFunc(this, &ManagedSubscription::OnCallback); 
     m_delegateHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_delegate); 
     m_nativeCallbackWrapper = new NativeCallbackWrapper(static_cast<CallbackPtr>(Marshal::GetFunctionPointerForDelegate(m_delegate).ToPointer())); 
     m_callback = callback; 
     } 

bool ManagedSubscription::OnCallback(const std::vector<Sample>& result, bool disconnected) 
    { 
    try 
    { 
     m_callback(samplesData, disconnected); 
     return true; 
    } 
    catch (Exception^ ex) 
    { 
     return false; 
    } 
    catch (Object^ ex) 
    { 
     return false; 
    } 
    } 

    //This is given to natice class which actually calls this callback (ManagedSubscription::OnCallback mentioned above) 
    const ManagedSubscription::Callback_t& ManagedSubscription::GetNativeCallback() 
    { 
    return m_nativeCallbackWrapper->m_callback; 
    } 

Das ist mein native C++ Code:

bool Publish(const std::vector<SampleType>& samples, bool disconnected) 
     { 
      try 
      { 
      //This actually calls managed callback (ManagedSubscription::OnCallback) 
      return m_subscriptionCallback(samples, disconnected); 
      } 
      catch (std::exception& e) 
      { 
      return false; 
      } 
      catch (...) 
      { 
      return false; 
      } 
     } 

Dies wird Stack-Trace von Crash:

KERNELBASE!RaiseException+68  cdb52105  00007ffb  00000001  
clr!RaiseTheExceptionInternalOnly+33b  cdee43f4  00007ffb  00000000  
clr!RaiseTheException+a4  cdee4460  00007ffb  00000002  
clr!RealCOMPlusThrow+69  cdeb6d72  00007ffb  43d60b70  
clr!Thread::RaiseCrossContextException+333  cdcd24cb  00007ffb  2fbadcf8  
clr!Thread::DoADCallBack+1a8  cdb69535  00007ffb  2fbade01  
clr!UM2MDoADCallBack+b3  cdb681dd  00007ffb  8a988a50  
clr!UMThunkStub+26d  bc090516  00007ffb  2fbaef70  
ManagedChartFeedInterface!DFS::Chart::HistoricalCache::TypedSubscription<DFS::Chart::ChartCache::ForexInstrumentInfo>::Publish+66 

Erste Zeile des Stapels Trace stellt Aufruf von systemeigenem Code return m_subscriptionCallback(samples, disconnected); in Publish dar, der oben erwähnt wird.

Mache ich etwas falsch beim Marshalling von Rückruf?
Ist es etwas mit App-Domains als Client-App verwandt App-Domain-Konzept?

Antwort

0

Ich habe eine ruhige und hilfreiche Antwort von anderen Seiten zu meinem Problem bekommen: Ich dachte, ich teile es hier mit. Hier ist Link dafür:

[https://msdn.microsoft.com/en-us/library/367eeye0.aspx][1] sagt, es ist nicht notwendig, den Delegierten Pin; Der Funktionszeiger bleibt gültig, selbst wenn der GC den Delegaten verlagert.

In den CoreCLR Quellen, es sieht aus wie Thread::DoADCallBack Anrufe Thread::RaiseCrossContextException nur über das END_DOMAIN_TRANSITION Makro, nachdem eine andere Ausnahme abgefangen wurde. Und Thread::DoADCallback verwendet dieses Makro nur, wenn die Anwendungsdomäne nicht übereinstimmt.