Roslyn 脚本引擎在用作委托时不会抛出运行时异常
Roslyn scripting engine does not throw runtime exception when used as delegate
我 运行 在使用 Roslyn 脚本引擎时遇到了麻烦。当我 运行 委托中的脚本时,我没有得到任何异常处理。
按预期工作的测试:
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...
}
我收到了失败消息,没有抛出异常。
我们缓存委托以加快编译速度,并且在测试期间我们发现 运行time 异常没有被抛出。所以我写了测试来重现这种情况。
我在文档中找不到任何描述调用期间没有抛出异常的提示。
有人能给我指点或提示为什么会这样吗?
您的代码有两个问题:
在第一个版本中,您正在捕获 Exception
,这意味着当达到 Assert.Fail
并抛出 AssertionException
时,该异常将被捕获并被忽略。
意思就是这里的RunAsync
和delegate没有区别,都不会抛出DivideByZeroException
.
RunAsync
和 ScriptRunner<T>
代表 return Task
。这意味着要实际等待它们完成或观察任何异常,您需要使用 await
。执行此操作后,您将看到您期望的 DivideByZeroException
。
您的 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();
但是只有当包含方法可以标记为 async
时才会编译,这不一定是您想要的(显示更多调用代码以澄清)。
我 运行 在使用 Roslyn 脚本引擎时遇到了麻烦。当我 运行 委托中的脚本时,我没有得到任何异常处理。
按预期工作的测试:
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...
}
我收到了失败消息,没有抛出异常。
我们缓存委托以加快编译速度,并且在测试期间我们发现 运行time 异常没有被抛出。所以我写了测试来重现这种情况。
我在文档中找不到任何描述调用期间没有抛出异常的提示。
有人能给我指点或提示为什么会这样吗?
您的代码有两个问题:
在第一个版本中,您正在捕获
Exception
,这意味着当达到Assert.Fail
并抛出AssertionException
时,该异常将被捕获并被忽略。意思就是这里的
RunAsync
和delegate没有区别,都不会抛出DivideByZeroException
.RunAsync
和ScriptRunner<T>
代表 returnTask
。这意味着要实际等待它们完成或观察任何异常,您需要使用await
。执行此操作后,您将看到您期望的DivideByZeroException
。
您的 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();
但是只有当包含方法可以标记为 async
时才会编译,这不一定是您想要的(显示更多调用代码以澄清)。