Error handling in X# vs VO
Posted: Fri Mar 12, 2021 3:21 pm
Hi All
I've started using X# and finding it amazing how i can just copy/paste code from VO (2.5b) into Visual Studio and it nearly (99.9%) works. Just having an issue with Error Handling.... and using ErrorBlock() - i can see examples about setting an ErrorBlock but this doesn't work. I was then told about "FirstChanceException" in .net and i've put an example together below that will work (with very little change) for our VO Web Application. (i can see there is a open issue here https://github.com/X-Sharp/XSharpPublic/issues/111)
Below is a working example and what it does
1. Set a ErrorBlock() as you would do in VO
2. Set FirstChanceException to call function on error FirstChanceHandler (and UnhandledException if you want)
3. This then checks ErrorBlock to see if there is one defined, and calls it. (you could then write to Audit Trail etc.
4. FirstChanceHandler then returns to RECOVER statement , (ti stores the VO Error in a Thread Store so we can get it back later)
5. In the Recover , it could check the Error (from the Thread) so see what to do (if anything), in my example i see if i can retry.
I know it doesn't continue with the next line (as in VO), but it does use ErrorBlock which i couldn't seem to do, and you only need to change code in your recover if you need to access the Error !
Ian
-------------
I've started using X# and finding it amazing how i can just copy/paste code from VO (2.5b) into Visual Studio and it nearly (99.9%) works. Just having an issue with Error Handling.... and using ErrorBlock() - i can see examples about setting an ErrorBlock but this doesn't work. I was then told about "FirstChanceException" in .net and i've put an example together below that will work (with very little change) for our VO Web Application. (i can see there is a open issue here https://github.com/X-Sharp/XSharpPublic/issues/111)
Below is a working example and what it does
1. Set a ErrorBlock() as you would do in VO
2. Set FirstChanceException to call function on error FirstChanceHandler (and UnhandledException if you want)
3. This then checks ErrorBlock to see if there is one defined, and calls it. (you could then write to Audit Trail etc.
4. FirstChanceHandler then returns to RECOVER statement , (ti stores the VO Error in a Thread Store so we can get it back later)
5. In the Recover , it could check the Error (from the Thread) so see what to do (if anything), in my example i see if i can retry.
I know it doesn't continue with the next line (as in VO), but it does use ErrorBlock which i couldn't seem to do, and you only need to change code in your recover if you need to access the Error !
Ian
-------------
Code: Select all
USING VO
USING System.Threading
BEGIN NAMESPACE Test
FUNCTION Start() AS VOID STRICT
LOCAL x AS USUAL
System.AppDomain.CurrentDomain:UnhandledException += ExceptionHandler
System.AppDomain.CurrentDomain:FirstChanceException += FirstChanceHandler
ErrorBlock({|oError| MyErrorHandler(oError) })
x:=1
DO WHILE TRUE
BEGIN SEQUENCE
x:=x+"Hello"
RECOVER
LOCAL oError AS Error
oError:=GetError()
IF ! oError==NULL_OBJECT .AND. oError:CanRetry
x:="" // So shouldn't crash next time */
LOOP
ENDIF
END SEQUENCE
EXIT
ENDDO
INTERNAL FUNCTION MyErrorHandler(oError AS Error) AS VOID
IF ! oError==NULL_OBJECT
/* Set Can Retry for our Test */
oError:CanRetry:=TRUE
ENDIF
INTERNAL FUNCTION GetError() AS Error
LOCAL oError AS Error
/* Get Current Error from Thread (using GetData) and NULL error in Thread */
oError:=(Error) Thread.GetData(Thread.GetNamedDataSlot("Error"))
Thread.SetData(Thread.GetNamedDataSlot("Error"),NULL)
RETURN oError
INTERNAL FUNCTION FirstChanceHandler( sender AS OBJECT, args AS System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs) AS VOID
LOCAL oError AS Error
LOCAL bErrorHandler AS CODEBLOCK
Thread.SetData(Thread.GetNamedDataSlot("Error"),oError)
oError:=ErrorBuild(args:Exception)
bErrorHandler:=ErrorBlock()
IF ! bErrorHandler==NULL_CODEBLOCK
eval(bErrorHandler,oError)
ENDIF
/* Store Error in Thread (SetData) so we can get it back later */
Thread.SetData(Thread.GetNamedDataSlot("Error"),oError)
STATIC FUNCTION ExceptionHandler( sender AS OBJECT, args AS UnhandledExceptionEventArgs) AS VOID
/* Can do the Same as the above */
END NAMESPACE