我使用Roslyn Scripting Engine遇到了麻烦。我在委托中运行脚本时没有异常处理。
测试按预期工作:
string script = @"var a=0; var b=2/a;";
var runner = CSharpScript.Create<object>(script);
var errors = runner.Compile();
Assert.IsTrue(errors.IsEmpty);
try
{
runner.RunAsync();
Assert.Fail("Where is the exception");
}
catch (System.Exception)
{
// everything is OK! Error thrown...
}
结果:没有断言。抛出异常。
这是使用委托对象的文本:
单元测试:
string script = @"var a=0; var b=2/a;";
var runner = CSharpScript.Create<object>(script);
var errors = runner.Compile();
var delegat = runner.CreateDelegate();
Assert.IsTrue(errors.IsEmpty);
try
{
delegat();
Assert.Fail("Where is the exception?");
}
catch (System.DivideByZeroException)
{
// everything is OK! Error thrown...
}
我收到了失败消息,没有抛出任何异常。
我们缓存代理以加速编译,在测试期间我们看到不会抛出运行时异常。所以我写了测试来重现这种情况。
我在文档中找不到任何提示,说明在调用期间没有抛出异常。
有人可以给我一个指针或暗示为什么会发生这种情况?
答案 0 :(得分:2)
您的代码存在两个问题:
在第一个版本中,您正在捕获Exception
,这意味着当达到Assert.Fail
并抛出AssertionException
时,会捕获并忽略该异常
这意味着此处RunAsync
和委托之间没有区别,它们都不会抛出DivideByZeroException
。
RunAsync
和ScriptRunner<T>
委托都返回Task
。这意味着要实际等待它们完成或观察任何异常,您需要使用await
。完成后,您会看到您期待的DivideByZeroException
。
答案 1 :(得分:0)
您的Main
在调度程序有机会调用delegat
之前完成执行。这是一个异步运行的任务。在调试器中检查它时可以看到:
要强制执行try...catch
范围内的执行,您可以使用:
try
{
delegat().Wait();
}
catch(System.AggregateException ex)
{
/* the inner exception of ex will be your DivideByZeroException */
}
在这种情况下,正确的异常类型是AggregateException
,see here why。
也可以使用await
的解决方案:
await delegat();
但是只有当contains方法可以标记为async
时才会编译,这不一定是你想要的(显示更多要调用的调用代码)。