本机到托管边界上的 CrossContext 异常
CrossContext exception on native to managed boundary
我开发了托管 C++ 应用程序,它 return 是 C# 客户端 ManagedSubscription
的一个对象。
ManagedSubscription
从 C# 客户端接收回调,在内部进行自己的回调以与本机 C++ 代码通信。
在跨越从本机到托管的边界时,我观察到崩溃。
我已将 try-catch
放入本机和托管回调中,但未被捕获。
这是我的托管 C++ 代码:
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;
}
这是我的原生 C++ 代码:
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;
}
}
这是崩溃的堆栈跟踪:
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
堆栈跟踪的第一行表示来自上述 Publish
中本机代码 return m_subscriptionCallback(samples, disconnected);
的调用。
我在编组回调时做错了什么吗?
它是否与应用程序域相关,因为客户端应用程序使用应用程序域概念?
我从其他网站得到了关于我同样问题的安静有用的答案:我也想在这里分享这个。这是 link:
[https://msdn.microsoft.com/en-us/library/367eeye0.aspx][1]表示不需要pin delegate;即使 GC 重新定位委托,函数指针也将保持有效。
在 CoreCLR 源代码中,看起来 Thread::DoADCallBack
仅通过 END_DOMAIN_TRANSITION
宏调用 Thread::RaiseCrossContextException
,在捕获到不同的异常之后。 Thread::DoADCallback
仅当应用程序域不匹配时才使用该宏。
我开发了托管 C++ 应用程序,它 return 是 C# 客户端 ManagedSubscription
的一个对象。
ManagedSubscription
从 C# 客户端接收回调,在内部进行自己的回调以与本机 C++ 代码通信。
在跨越从本机到托管的边界时,我观察到崩溃。
我已将 try-catch
放入本机和托管回调中,但未被捕获。
这是我的托管 C++ 代码:
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;
}
这是我的原生 C++ 代码:
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;
}
}
这是崩溃的堆栈跟踪:
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
堆栈跟踪的第一行表示来自上述 Publish
中本机代码 return m_subscriptionCallback(samples, disconnected);
的调用。
我在编组回调时做错了什么吗?
它是否与应用程序域相关,因为客户端应用程序使用应用程序域概念?
我从其他网站得到了关于我同样问题的安静有用的答案:我也想在这里分享这个。这是 link:
[https://msdn.microsoft.com/en-us/library/367eeye0.aspx][1]表示不需要pin delegate;即使 GC 重新定位委托,函数指针也将保持有效。
在 CoreCLR 源代码中,看起来 Thread::DoADCallBack
仅通过 END_DOMAIN_TRANSITION
宏调用 Thread::RaiseCrossContextException
,在捕获到不同的异常之后。 Thread::DoADCallback
仅当应用程序域不匹配时才使用该宏。