在非CLR创建的线程中进行CLR托管异常处理
||
问题:
从非托管代码进入CLR的线程中未处理的异常不会触发\“ normal \”未处理的异常CLR处理。
在下面的代码中,使用C从C ++调用
CSSimpleObject.GetstringLength()
\“ 1 \”在调用线程(非CLR创建的线程)中引发异常,
\“ 2 \”在新的Thread()(CLR创建的线程)中引发异常。
如果\“ 1 \”
从不调用CurrentDomain_UnhandledException()。
应用程序域和进程将保持加载和运行状态,您只会得到失败。
万一\“ 2 \”(预期行为)
调用CurrentDomain_UnhandledException()。
该过程被杀死。
问题:
要获得“正常”行为必须做什么?
样例代码:
下面的代码基于Visual Studio 2010 \“ CppHostCLR \”代码示例
来自“所有互操作和融合样本”。
RuntimeHost(C ++):
PCWSTR pszStaticMethodName = L\"GetStringLength\";
PCWSTR pszStringArg = L\"1\";
//PCWSTR pszStringArg = L\"2\";
hr = pClrRuntimeHost->ExecuteInDefaultAppDomain(pszAssemblyPath,
pszClassName, pszStaticMethodName, pszStringArg, &dwLengthRet);
if (FAILED(hr))
{
wprintf(L\"Failed to call GetStringLength w/hr 0x%08lx\\n\", hr);
goto Cleanup;
}
托管代码(C#):
public class CSSimpleObject
{
public CSSimpleObject()
{
}
//------8<----------
public static int GetStringLength(string str)
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
switch (str)
{
case \"1\":
throw new Exception(\"exception in non-CLR-created thread\");
case \"2\":
Thread thread = new Thread(new ThreadStart(WorkThreadFunction));
thread.Start();
break;
}
return str.Length;
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Console.WriteLine(\"CurrentDomain_UnhandledException:\" + e.ToString());
Console.ReadKey();
}
public static void WorkThreadFunction()
{
throw new Exception(\"\"exception in CLR-created thread\"\");
}
到目前为止的研究:
MSDN最初暗示,非CLR创建的线程中未处理的异常应该或多或少地“自然地”表现-请参见“托管线程中的异常”
公共语言运行时允许线程中大多数未处理的异常自然进行。在大多数情况下,这意味着未处理的异常会导致应用程序终止。\“
\“ Most \”表示在CLR创建的线程内部,线程异常中止和Application Domain卸载异常的处理方式不同。在非CLR线程中
\“它们正常进行,导致应用程序终止。”
进一步的研究使我找到了“ CLR中未处理的异常处理”,在其中我发现了以下内容:
\“如果未在托管方法中处理异常,则该异常将退出CLR,但会继续作为本机SEH异常向上传播到堆栈(托管异常表示为本机SEH异常)...
操作系统未处理异常过滤器(UEF)机制可能并不总是导致触发CLR的未处理异常处理。
在正常情况下,这将按预期工作,并且将触发CLR的未处理异常处理。但是,在某些情况下,这可能不会发生。”
上面的代码有什么问题,或者如何更改它以便触发CLR的未处理异常处理?
更新(2011-05-31):
我刚刚发现了一个旧的错误报告,“从非托管状态调用托管代码并引发异常时,未调用UnhandledExceptionEventHandler-http://tinyurl.com/44j6gvu”,Microsoft确认这是“越野车”行为:
感谢您抽出宝贵时间报告此问题。该行为确实是由CLR执行引擎和CRT竞争UnhandledExceptionFilter引起的错误。 CLR的体系结构已在支持此方案的4.0版本中进行了修订。
更新(2011-06-06):
为什么正确解决这个问题很重要?
如果您正在创建主机环境,则开发人员希望异常处理中的行为一致
除非有一种方法可以在本机线程中触发“常规CLR异常处理”,否则这意味着您始终必须将执行转移到托管线程(例如,进入线程池)
仍然有少量的代码将执行从本机线程转移到托管线程...必须捕获所有异常并以某种方式不同地处理这种情况
注意:从表面上看,通过ѭ3更改CLR行为会使情况变得更糟,因为它最终掩盖了原始异常(即,不是内存不足,您最终会看到threadAborts-不知道原始错误源于何处!)
没有找到相关结果
已邀请:
1 个回复
哩翔购