How do I ensure an operation won't crash the whole app? - c#

I have an application performing some additional jobs like cleaning old logs, sending notifications and so on. If one job fails I don't want the whole application to stop working and not perform jobs what left.
So for example,
await SendUsersBirthdayEmailsAsync(); // <-- if something fails while trying to send birthday emails here, I don't want the app to stop working and not clean logs and so on...
await DeleteOutdatedLogsAsync();
await SendSystemNotificationsAsync();
What would you recommend me to go with?

Use try-catch block on every part of the code that can fail.
Depending on what you need, use try-catch-finally block.
On every catch block, log the exception however you want. I use Nlog for logging so i suggest looking into that.
try{
//do work here
}
catch(Exception e){
//log exception here
}
//optional
finally{
//do optional needed work here
}
Something like this:
public bool SendUsersBirthdayEmailsAsync(){
try{
SendMail();
}
catch(Exception e){
LogException(e);
}
//optional
finally{
OptionalWork();
}
}
EDIT: About avoiding using generic exception
You can always use multiple catch blocks any define different behavior for each type of exception. This is useful when you know what kind of exception can be expected.
Example:
public bool SendUsersBirthdayEmailsAsync(){
try{
SendMail();
}
catch (ThreadAbortException tae)
{
LogException(tae);
//do something specific
}
catch (ThreadInterruptedException tie)
{
LogException(tie);
//do something specific
}
catch(Exception e){
LogException(e);
}
//optional
finally{
OptionalWork();
}
}
EDIT 2: Official Microsoft guidance for exception handling.
Use try/catch blocks around code that can potentially generate an exception and your code can recover from that exception. In catch blocks, always order exceptions from the most derived to the least derived. All exceptions derive from Exception. More derived exceptions are not handled by a catch clause that is preceded by a catch clause for a base exception class. When your code cannot recover from an exception, don't catch that exception. Enable methods further up the call stack to recover if possible.
Clean up resources allocated with either using statements, or finally blocks. Prefer using statements to automatically clean up resources when exceptions are thrown. Use finally blocks to clean up resources that don't implement IDisposable. Code in a finally clause is almost always executed even when exceptions are thrown.

Task<Task> task = (SendUsersBirthdayEmailsAsync()
.ContinueWith(x => Task.WhenAll(DeleteOutdatedLogsAsync(), SendSystemNotificationsAsync())));
await await task;
For more general sample the below code provided:
class TaskTest
{
public async void Start()
{
await (
(await One().ContinueWith(x => Task.WhenAll(Two(), Three())))
.ContinueWith(x=> Four()));
}
private async Task One()
{
await Task.Delay(5000);
Console.WriteLine("1");
throw new Exception();
}
private async Task Two()
{
await Task.Delay(2000);
Console.WriteLine("2");
throw new Exception();
}
private async Task Three()
{
await Task.Delay(3000);
Console.WriteLine("3");
throw new Exception();
}
private async Task Four()
{
await Task.Delay(1000);
Console.WriteLine("4");
throw new Exception();
}
}
running this code shows that throwing exceptions inside tasks does not halt the whole program.

If you are already doing it with a scheduler why not separate it into smaller tasks? In that way if one action fails it will not bring down all the others. Also it is a good practice to have many smaller applications with dedicated responsibilities rather than a generic one that does everything.

If you are looking for a reliable option to ensure the process is completed and is traceable, you can go with Hangfire. You can put your retry logic in case of failures by handling exceptions also.

Since the name of the methods suggests, that these methods are independent of each other, just make sure each returns an await-able task and put them into a list. Your use of await suggests, they already do.
Put one try-catch around it and catch the AggregateExeption.
List<Task> tasks = new List<Task>();
try
{
tasks.Add(SendUsersBirthdayEmailsAsync());
tasks.Add(DeleteOutdatedLogsAsync());
tasks.Add(SendSystemNotificationsAsync());
Task.WhenAll(tasks); // waits for all tasks to finish
}
catch (Exception e)
{
//Log e.ToString(); will give you all inner exceptions of the aggregate exception as well, incl. StackTraces, so expect possibly a lot of chars, wherever you log it.
}
This may also speed things up, because they are now running in parallel. But since they all seem to work on a database (most likely the same), it might not be much, if at all, because of the scheduling overhead.

You can implement your methods using the Try-Pattern and have them return Boolean.
Let every method handle exceptions on it's own so that you are sure no unhandled exceptions can be thrown to kill off your application.
In case a failure will result in unrecoverable program state, the methods should return false and your application should quit in a clean way by itself.

Unobserved Task Exceptions
await SendUsersBirthdayEmailsAsync(); // uses TaskScheduler
Since you are working with a TaskScheduler, check out TaskScheduler.UnobservedTaskException.
Occurs when a faulted task's unobserved exception is about to trigger
exception escalation policy, which, by default, would terminate the
process.

You need to use Try-Catch in every function as follow.
try{
//write your code
}
catch(Exception e){
//your exception will be here
}
You can generate a log file for that exception.
Just Do one thing for your log File. Create A Log Class and a log file generate function.
call that function in catch area of your all functions.
Let you create a Log class with name clsLog. and a static function with name InsertLog(string exception, string functionname).
Use this log method in your all function as follow.
public void insertcity()
{
try
{
//Insert city programming
}
catch (exception ex)
{
clsLog.InsertLog(ex.Message,"insertCity");
//do something else you want.
}
}
Hope it will help.

i think if u use
try{
//your nice work
}
catch(Exception e){
//hmm.. error ok i will show u
}
//optional
finally{
//again start the operation if u failed here.
}
i also make the same application in which when some error comes and failed then in the catch exception i make the log in system and also again restart the application in the finally. so it will never die.

I would recommend to found out what exception you getting from async to actually get this exception and understand it you can use on a main Thread:
MyTask().GetAwaiter().GetResult();
This will allow you to see the text of the actual exception that you have on your await Thread.
And a little bit if you don't want a main Thread to return to the line with await you also can use:
await SendUsersBirthdayEmailsAsync().ConfigureAwait(false);
This will just continue your Task on the nearest free Thread.
But need to say this will cause an exception on Android because it have some restrictions of using Threads.
In the case you don't want to waste your time or don't need to handle the exception manually and fixing it try, catch finally is always an option.

The answer that Andreas used - fits what I was thinking - however I would make one more piece - A Cancellation Token - with a time limit on how long you would think is enough time - so that everything completes.
The individual tasks in the Wait means that they all come back together at that point while they execute seperately. You can catch the agreggate exceptions if they occur - and then determine if it was timeout - or something you need to log.
The Two suggestions on UnhandledException and UnhandledTask Exception SHOULD be included also - for what ever reason that they stop..
I would also think about making this a Windows service so that you can pass the cancellation token into the tasks from startup - and have a timer on when the service actually runs - instead of a scheduled task - then with all the exception handling you can see what the log tells you over time - which feels a little more resilient than a console app to me - but that is how we normally run tasks in this vein.
You can start and stop a service like this in a console app for testing - and then hand it off into a project that handles the OnStart and OnStop events - passing the Cancellation token in - OnStop would cancel the token and stop the service loops.

Related

Worker service process stops for no apparent reason when using async

I've set up a really simple work service project, with just a single worker (for now). Here's the complete code for the ExecuteAsync method:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
var engine = new CrawlerEngine(_logger);
try
{
await engine.CrawlAsync(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
}
await Task.Delay(TimeSpan.FromMinutes(1));
}
_logger.LogInformation("Worker stopping at: {time}", DateTimeOffset.Now);
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
}
}
As you can see it's fairly simple, just an infinite loop until cancellation and the only real logic in there is all wrapped inside the CrawlerEngine.
Here's the catch, if I run the service it'll run for maybe a couple of minutes and then just exit. It'll not log "Worker stopping" nor an exception, it just plain stops the entire process.
I tried changing all the async code inside CrawlAsync, so it's completely synchronous. This removes the problem and leaves me puzzled.
Every Async method I have inside CrawlAsync returns either Task or Task and is awaited.
So I'm figuring maybe some of the async code throws an exception that isn't caught by the try-catch, however to the best of my knowledge the exception should "bubble up" and be caught as long as you're using await.
I even added an AppDomain.UnhandledException handler, that catches nothing as well.
Do you have any ideas what the heck is going on here?
EDIT: Just for clarification I'm asking whether there's any hidden details to async, that can cause it to crash an entire process with no amount of try-catch being able to see it?
EDIT 2: Seems what's crashing my process is WebClient.DownloadStringAsTaskAsync as well as HttpClient.GetStringAsync. Whenever I use either one, my process just exits at some point. Using a synchronous method for downloading string doesn't cause this.
I finally figured out what was exiting the process: a StackOverflowException.
This explains the lack of logging etc.
I've solved it by changing a recursive method (which called HttpClient.GetStringAsync) to a for loop.
Why it didn't throw StackOverflow when using the non-async variant of GetString is still beyond me though.

How can an exception bubble up beyond this task?

I thought this approach would be safe, in that it wouldn't allow exceptions to propagate. A colleague of mine suggested that the exceptions may need to be observed on the main thread, and should thus be passed up to the main thread. Is that the answer? Can you see how an exception could leak through this?
private static void InvokeProcessHandlers<T>(List<T> processHandlers, Action<T> action)
{
// Loop through process handlers asynchronously, giving them each their own chance to do their thing.
Task.Factory.StartNew(() =>
{
foreach (T handler in processHandlers)
{
try
{
action.Invoke(handler);
}
catch (Exception ex)
{
try
{
EventLog.WriteEntry(ResourceCommon.LogSource,
String.Format(CultureInfo.CurrentCulture, "An error occurred in a pre- or post-process interception handler: {0}", ex.ToString()),
EventLogEntryType.Error);
}
catch (Exception)
{
// Eat it. Nothing else we can do. Something is seriously broken.
}
continue; // Don't let one handler failure stop the rest from processing.
}
}
});
}
By the way, a stack trace is indeed showing that an exception is leaking from this method.
The exception is AccessViolation, and I believe it has to do with the code that calls this method:
InvokeProcessHandlers<IInterceptionPostProcessHandler>(InterceptionPostProcessHandlers, handler => handler.Process(methodCallMessage, methodReturnMessage));
The getter for InterceptionPostProcessHandlers contains this:
_interceptionPreprocessHandlers = ReflectionUtility.GetObjectsForAnInterface<IInterceptionPreprocessHandler>(Assembly.GetExecutingAssembly());
Just make sure to check parameter for null references before you iterate
other than that there is nothing wrong as log writing is not something to stop the execution, but i would recommend to make it more clean and maintainable by encapsulating the logging into a mothod like:
bool Logger.TryLog(params);
and inside this method do the try with a catch that returns false and if you want to handle it in client code do it and if you dont never mind just call the logger in a clean encapsulated way
A colleague of mine suggested that the exceptions may need to be
observed on the main thread, and should thus be passed up to the main
thread.
How can it be "passed up to the main thread"? The main thread is away and doing its own thing.
The best you can do is to make it configurable and accept an ExceptionHandler delegate that is called.

Removing excessive try-catch blocks

I'm refactoring a medium-sized WinForms application written by other developers and almost every method of every class is surrounded by a try-catch block. 99% of the time these catch blocks only log exceptions or cleanup resources and return error status.
I think it is obvious that this application lacks proper exception-handling mechanism and I'm planning to remove most try-catch blocks.
Is there any downside of doing so? How would you do this? I'm planning to:
To log exceptions appropriately and prevent them from propagating to the user, have an Application.ThreadException handler
For cases where there's a resource that needs cleanup, leave the try-catch block as it is
Update: Using using or try-finally blocks is a better way. Thanks for the responses.
In methods that "return-false-on-error", let the exception propagate and catch it in the caller instead
Any corrections/suggestions are welcome.
Edit: In the 3rd item, with "return-false-on-error" I meant methods like this:
bool MethodThatDoesSomething() {
try {
DoSomething(); // might throw IOException
} catch(Exception e) {
return false;
}
}
I'd like to rewrite this as:
void MethodThatDoesSomething() {
DoSomething(); // might throw IOException
}
// try-catch in the caller instead of checking MethodThatDoesSomething's return value
try {
MethodThatDoesSomething()
} catch(IOException e) {
HandleException(e);
}
"To log exceptions appropriately and prevent them from propagating to the user, have an Application.ThreadException handler"
Would you then be able to tell the user what happened? Would all exceptions end up there?
"For cases where there's a resource that needs cleanup, leave the try-catch block as it is"
You can use try-finally blocks as well if you wish to let the exception be handled elsewhere. Also consider using the using keyword on IDisposable resources.
"In methods that "return-false-on-error", let the exception propagate and catch it in the caller instead"
It depends on the method. Exceptions should occur only in exceptional situations. A FileNotFoundException is just weird for the FileExists() method to throw, but perfectly legal to be thrown by OpenFile().
For cleanup rather use try-finally or implement the IDisposable as suggested by Amittai. For methods that return bool on error rather try and return false if the condition is not met. Example.
bool ReturnFalseExample() {
try {
if (1 == 2) thow new InvalidArgumentException("1");
}catch(Exception e) {
//Log exception
return false;
}
Rather change to this.
bool ReturnFalseExample() {
if (1 == 2) {
//Log 1 != 2
return false;
}
If i'm not mistaken try catches are an expensive process and when possible you should try determine if condition is not met rather then just catching exceptions.
}
As an option for "return-false-on-error" you can clean up the code this way:
static class ErrorsHelper {
public static bool ErrorToBool(Action action) {
try {
action();
return true;
} catch (Exception ex) {
LogException(ex);
return false;
}
}
private static void LogException(Exception ex) {
throw new NotImplementedException();
}
}
and usage example:
static void Main(string[] args) {
if (!ErrorToBool(Method)) {
Console.WriteLine("failed");
} else if (!ErrorToBool(() => Method2(2))) {
Console.WriteLine("failed");
}
}
static void Method() {}
static void Method2(int agr) {}
The best is as said by others, do exception handling at 1 place. Its bad practice to conceal the raised exception rather than allowing to bubble up.
You should only handle only the exceptions that you are expecting, know how to handle and they are not corrupt the state of your application, otherwise let them throw.
A good approach to follow is to log the exception first, then Restart your application, just like what Microsoft did when office or visual studio crashing. To do so you have to handle the application domain unhanded exception, so:
AppDomain.CurrentDomain.UnhandledException += OnCurrentDomainUnhandledException;
//Add these two lines if you are using winforms
Application.ThreadException += OnApplicationThreadException;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
private void OnCurrentDomainUnhandledException(object sender, System.Threading.ThreadExceptionEventArgs e)
{
//Log error
//RestartTheApplication
}
Here an example on how to restart your application.
I think your strategy of removing try/catch block which just appear to do generic thoughtless logging is fine. Obviously leaving the cleanup code is necessary. However, I think more clarification is needed for your third point.
Return false on error methods are usually OK for things where exceptions are unavoidable, like a file operation in your example. Whereas I can see the benefit of removing exception handling code where it's just been put in thoughtlessly, I would consider carefully what benefit you get by pushing responsibility for handling an exception of this kind higher up in the call chain.
If the method is doing something very specific (it's not generic framework code), and you know which callers are using it, then I'd let it swallow the exception, leaving the callers free of exception handling duties. However, if it's something more generic and maybe more of a framework method, where you're not sure what code will be calling the method, I'd maybe let the exception propagate.
You may try to use AOP.
In AOP through PostSharp, for example, you can handle exceptions in one central place (piece of code) as an aspect.
Look at the examples in documentation to have an idea => Docs on Exception Handling with PostSharp.
we can remove try and catch by adding condition Like
string emailAddresses = #"^([\w\.\-]+)#([\w\-]+)((\.(\w){2,3})+)$";
if (!Regex.IsMatch(Email, emailAddresses))
{
throw new UserFriendlyException($"E-mail Address Is not Valid");
}**strong text**

C# Returning something from exception handle

I have the following code in a class of mine. The purpose of this class is to get the balance from a web server. Just in case something goes wrong with getting the balance. I will handle a exception. However, all this is easy to do. But I am left wondering what do I return in my catch statement.
Most of the examples I looked at just write to the console using:
Console.WriteLine(ex.Message);
That is all very well. But in a real application what do most developers do?
//Download only when the webclient is not busy.
if (!wc.IsBusy)
{
// Sleep for 1/2 second to give the server time to update the balance.
System.Threading.Thread.Sleep(500);
try
{
// Download the current balance.
wc.DownloadStringAsync(new Uri(strURL));
}
catch (WebException ex)
{
Console.Write("GetBalance(): " + ex.Message);
}
}
else
{
Console.Write("Busy please try again");
}
My function at the moment returns void. And I am just wondering what else I would return if the webclient is busy?
Many thanks for any advice,
Do not catch an exception if you cannot handle it. If you return just some value, the calling method has to check if the value is a real result or just an indicator of an exception. And now this method must decide what to do and return. And the method calling this method. And the method...
So just let the exception bubble up the stack and catch it somewhere where you can handle it. Maybe directly below the user interface and then display a message box asking if the user wants to retry or display information how to solve the problem. If you have no user interface, catch it somewhere where you can solve the problem and retry. If it is a temporary problem, retry the whole task at a reasonable level until the call succeeds.
If you want to log something, use the following pattern to log the exception an rethrow it.
try
{
DoStuff();
}
catch (Exception exception)
{
Log(exception.ToString());
throw;
}
Note that it is throw; and not throw exception;. If you do the later, you lose the original stack trace. If you can infer more details about the cause of the exception, you should wrap the caught exception into a more meaningful exception with additional information.
try
{
DoStuff();
}
catch (SpecificMeaninglessException exception)
{
Log(exception.ToString());
throw new MeaningfulException("Details about the error.", exception);
}
catch (Exception exception)
{
Log(exception.ToString());
throw;
}
You should use ex.ToString() method
Exception.Message
contains a simple description of the exception (e.g. "Object reference not set...").
Exception.ToString()
contains a description of the exception along with a complete stack trace.
Exception Handling Best Practices in .NET
You could re-run the method if the client is busy but wait a certain time before retries? Potentially with a failure after x retries.
If instead you wish to move on and simply log the problem, your catch statement could log the exception to a file-based log, event viewer, submit to a database, raise an alert (email, sms etc.) if it is necessary.
Depends on the severity of the exception.
I would suggest looking into The Exception Block from Patterns & Practices
If you're only interested in viewing the exception you should re throw the exception so who-ever is planning on handling it will still get it.
You certainly don't want to mask an unhandled exception. Let that bubble up through the stack. But if you are asking what to return if the web client is just busy, how about
returning either a random interval or some meaningful interval that the function caller should wait before attempting to download the balance again? A random number could distribute load or otherwise mitigate a collision problem. A more meaningful interval could be sent back based on the the current state of the server.

Is there a good method in C# for throwing an exception on a given thread

The code that I want to write is like this:
void MethodOnThreadA()
{
for (;;)
{
// Do stuff
if (ErrorConditionMet)
ThrowOnThread(threadB, new MyException(...));
}
}
void MethodOnThreadB()
{
try
{
for (;;)
{
// Do stuff
}
}
catch (MyException ex)
{
// Do the right thing for this exception.
}
}
I know I can have thread B periodically check, in thread safe way, to see if a flag has been set by thread A, but that makes the code more complicated. Is there a better mechanism that I can use?
Here is a more fleshed out example of periodically checking:
Dictionary<Thread, Exception> exceptionDictionary = new Dictionary<Thread, Exception>();
void ThrowOnThread(Thread thread, Exception ex)
{
// the exception passed in is going to be handed off to another thread,
// so it needs to be thread safe.
lock (exceptionDictionary)
{
exceptionDictionary[thread] = ex;
}
}
void ExceptionCheck()
{
lock (exceptionDictionary)
{
Exception ex;
if (exceptionDictionary.TryGetValue(Thread.CurrentThread, out ex))
throw ex;
}
}
void MethodOnThreadA()
{
for (;;)
{
// Do stuff
if (ErrorConditionMet)
ThrowOnThread(threadB, new MyException(...));
}
}
void MethodOnThreadB()
{
try
{
for (;;)
{
// Do stuff
ExceptionCheck();
}
}
catch (MyException ex)
{
// Do the right thing for this exception.
}
}
This is NOT a good idea
This article talks about ruby's timeout library. which throws exceptions across threads.
It explains how doing such a thing is fundamentally broken. It's not just broken in ruby, it's broken anywhere that throws exceptions across threads.
In a nutshell, what can (and does) happen is this:
ThreadA:
At some random time, throw an exception on thread B:
ThreadB:
try {
//do stuff
} finally {
CloseResourceOne();
// ThreadA's exception gets thrown NOW, in the middle
// of our finally block and resource two NEVER gets closed.
// Obviously this is BAD, and the only way to stop is to NOT throw
// exceptions across threads
CloseResourceTwo();
}
Your 'periodic checking' example is fine, as you're not actually throwing exceptions across threads.
You're just setting a flag which says "throw an exception the next time you look at this flag", which is fine as it doesn't suffer from the "can be thrown in the middle of your catch or finally block" problem.
However, if you're going to do that, you may as well just be setting an "exitnow" flag, and using that and save yourself the hassle of creating the exception object. A volatile bool will work just fine for that.
There are enough problems with exceptions that can be thrown on threads by other mechanisms, like aborting threads and the likes, that you should find another way of doing it.
An exception is a mechanism used to signal that a process has experienced something exceptional that it cannot deal with. You should try to avoid writing the code so that an exception is used to signal that something else has experienced something exceptional.
That other thread will most likely not know how to handle the exception in all cases where it could be thrown by your code.
In short, you should find some other mechanism for aborting your threads than using exceptions.
Use event objects or similar to tell a thread to abort its processing, that's the best way.
What Orion Edwards is saying is not entirely true: is not the "only" way.
// Obviously this is BAD, and the only way to stop is to NOT throw
// exceptions across threads
Using CER (Constrained Execution Regions) in C# allows you to release your resources as an atomic operation, protecting your code from inter-thread exceptions. This technique is used by several classes of the .NET Framework which work with Windows' native API, where an unreleased handle may cause a memory leak.
See http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions.aspx
The following example shows how to reliably set handles by using the PrepareConstrainedRegions method. To reliably set a handle to a specified pre-existing handle, you must ensure that the allocation of the native handle and the subsequent recording of that handle within a SafeHandle object is atomic. Any failure between these operations (such as a thread abort or out-of-memory exception) will result in the native handle being leaked. You can use the PrepareConstrainedRegions method to make sure that the handle is not leaked.
As simple as:
public MySafeHandle AllocateHandle()
{
// Allocate SafeHandle first to avoid failure later.
MySafeHandle sh = new MySafeHandle();
RuntimeHelpers.PrepareConstrainedRegions();
try { }
finally // this finally block is atomic an uninterruptible by inter-thread exceptions
{
MyStruct myStruct = new MyStruct();
NativeAllocateHandle(ref myStruct);
sh.SetHandle(myStruct.m_outputHandle);
}
return sh;
}
While researching another issue, I came across this article which reminded me of your question:
Plumbing the Depths of the ThreadAbortException using Rotor
It shows the gyrations that .NET goes through to implement Thread.Abort() -- presumably any other cross-thread exception would have to be similar. (Yeech!)
I'm interested to know why you would want to do this. There's not an easy way to do it, because it's not a good practice. You should probably go back to your design and figure out a cleaner way to accomplish the end goal.
I don't think that's a good idea..
Take another crack at this problem - Try using some other mechanism like shared data to signal between threads.
Like the others, I'm not sure that's such a good idea, but if you really want to do it, then you can create a subclass of SynchronizationContext that allows posting and sending delegates to the target thread (if it's a WinForms thread the work is done for you as such a subclass already exists). The target thread will have to implement some sort of a message pump equivalent though, to receive the delegates.
#Orion Edwards
I take your point about an exception being thrown in the finally block.
However, I think there is a way - using yet another thread - of using this exception-as-interrupt idea.
Thread A:
At some random time, throw an exception on thread C:
Thread B:
try {
Signal thread C that exceptions may be thrown
//do stuff, without needing to check exit conditions
Signal thread C that exceptions may no longer be thrown
}
catch {
// exception/interrupt occurred handle...
}
finally {
// ...and clean up
CloseResourceOne();
CloseResourceTwo();
}
Thread C:
while(thread-B-wants-exceptions) {
try {
Thread.Sleep(1)
}
catch {
// exception was thrown...
if Thread B still wants to handle exceptions
throw-in-B
}
}
Or is that just silly?

Categories