Reputation: 58
I run into troubles using the Roslyn Scripting Engine. I get no exception handling when I run a script within a delegation.
Test that works as expected:
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...
}
Result: No Assertion. The Exception was thrown.
Here's the text using a delegate object:
Unittest:
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...
}
I got the fail message and no exception was thrown.
We cache the delegates to speed up the compilation and during a test we see that runtime exceptions are not thrown. So I wrote the test to reproduce this situation.
I can't find any hint in the docs which describes that there are no exceptions thrown during the invoke.
Can someone give me a pointer or a hint why this happens?
Upvotes: 2
Views: 752
Reputation: 8726
Your Main
finishes execution before the scheduler gets a chance to invoke delegat
. It is a task that will run asynchronously. You can see that when you inspect it in the debugger:
To force execution inside the scope of the try...catch
, you can use this:
try
{
delegat().Wait();
}
catch(System.AggregateException ex)
{
/* the inner exception of ex will be your DivideByZeroException */
}
The correct type of exception to expect in this case is the AggregateException
, see here why.
A solution with await
is also possible:
await delegat();
but this will compile only when the containing method can be marked async
which is not necessarily what you want (show more of the calling code to clarify).
Upvotes: 0
Reputation: 244827
There are two issues with your code:
In the first version, you're catching Exception
, which means that when the Assert.Fail
is reached and throws AssertionException
, that exception is then caught and ignored.
This means that there is no difference between RunAsync
and delegate here, neither of them throws DivideByZeroException
.
Both RunAsync
and the ScriptRunner<T>
delegate return Task
. That means to actually wait for them to complete or to observe any exceptions, you need to use await
. Once you do that, you will see the DivideByZeroException
that you're expecting.
Upvotes: 2