Scalable approach for control flow of exception manager in C#? [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
In case number of nested try-catches happen to be many, e.g. a 100, is there any other way than simply writing 100 nested try-catches in the following manner?
try{
....
} catch(exception ex1)
try{
....
} catch(exception ex2) {
try{
}
....

You're free to nest try/catches multiple levels deep if you want.
try
{
operation1();
}
catch (Exception e)
{
try
{
operation2();
}
catch (Exception e2)
{
// etc
}
}

Given you need to this 100 times and have to use exception for your control flow (which should be avoided if possible). You could use some wrapper, like this:
public class ExWrapper
{
private readonly Action _action;
private readonly ExWrapper _prev;
private ExWrapper(Action action, ExWrapper prev = null)
{
_action = action;
_prev = prev;
}
public static ExWrapper First(Action test)
{
return new ExWrapper(test);
}
public ExWrapper Then(Action test)
{
return new ExWrapper(test, this);
}
public void Execute()
{
if (_prev != null)
try
{
_prev.Execute();
}
catch (Exception)
{
_action();
}
else
_action();
}
}
This allows you to chain actions, where the next action is only executed if the first one throws. You can use it as in the following example:
ExWrapper.First(() => { Console.WriteLine("First"); throw new Exception(); })
.Then( () => { Console.WriteLine("Second"); throw new Exception(); })
.Then( () => { Console.WriteLine("Third"); throw new Exception(); })
.Then( () => { Console.WriteLine("Fourth"); })
.Execute();
This executes all actions or lambdas in the given order, but will only execute the following action if the first throws. The example above prints:
First
Second
Third
Fourth
If you remove the throws in the example:
ExWrapper.First(() => { Console.WriteLine("First"); })
.Then( () => { Console.WriteLine("Second"); })
.Then( () => { Console.WriteLine("Third"); })
.Then( () => { Console.WriteLine("Fourth"); })
.Execute();
Only the first action is executed, resulting in the following output:
First

Just write another try-block inside the catch-block.
try {
//task A
} catch(Exception ex) {
try {
//task B
}
}

Another option would be to move your tasks to methods that return a bool indicating success, and then you don't have to nest your try/catches:
public static bool TrySomething(string someInput)
{
bool result = true;
try
{
// do something with someInput
}
catch
{
result = false;
}
return result;
}
public static bool TrySomethingElse(string someInput)
{
bool result = true;
try
{
// do something with someInput
}
catch
{
result = false;
}
return result;
}
Then in your main code, you could do:
string data = "some data";
if (!TrySomething(data))
{
TrySomethingElse(data);
}

Nested try-catch use a lot of resources and if they get out of hand they can significantly reduce the performance of your program. How ever, you can sequentially add catch blocks:
try
{
//code here
}catch(SomeException ex)
{
//Display what the specific exception was
}catch(SomeOtherException ex)
{
//Display what the specific exception was
}

Related

Unit test is running forever with Tasks

I have a unit test which is running forever:
[Test]
public bool test()
{
manager.Send(10);
Thread.Sleep(1000);
manager.Messages.Should().HaveCount(10);
return true;
}
manager.Send() method is:
private void Send()
{
try
{
var entities = GetAllEntities();
foreach (var group in entities.GroupBy(r => r.Priority))
{
var tasks = group.Select(entity => Task.Factory.StartNew(() => manager.SendEntity(entity))).ToList();
Task.WaitAll(tasks.ToArray());
if (tasks.All(r => r.Result.Result == true))
{
// some code here...
}
}
}
catch (Exception e)
{
logger.FatalException(e.Message, e);
}
finally
{
logger.Info("End...");
}
}
and SendEntity() method:
public Task<bool> SendEntity(DeferredEntity entity)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
try
{
logger.Info("Sending entity {0} with params: {1}", entity.Entity, GetEntityParams(entity));
server.SendToServer(entity, (response, result) =>
{
taskCompletionSource.SetResult(result);
});
}
catch (Exception e)
{
logger.FatalException(e.Message, e);
}
return taskCompletionSource.Task;
}
in unit test manager.Send(10) is running forever. I debuged the code and I see that the problem is in
if (tasks.All(r => r.Result.Result == true))
the debugger stops on this line and sleeps forever. What I am doing wrong? I added return value of unit test method to bool (async methods doesn't throw exceptions in void methods). But it doesn't help. Do you have any suggestions?
You get the deadlock there.
First of all you don't have to start the new Thread with
Task.Factory.StartNew(() => manager.SendEntity(entity)
It seems SendToServer is already async.
It also a bad practice to use the Task.Wait***/Task.Result, use the async flow
private async Task Send()
{
try
{
var entities = GetAllEntities();
foreach (var group in entities.GroupBy(r => r.Priority))
{
var tasks = group
.Select(entity => manager.SendEntity(entity))
.ToArray();
var results = await Task.WhenAll(tasks);
if (results.All(result => result))
{
// some code here...
}
}
}
catch (Exception e)
{
logger.FatalException(e.Message, e);
}
finally
{
logger.Info("End...");
}
}
But if you don't want to rewrite the Send Method you can use .ConfigureAwait(false)
return taskCompletionSource.Task.ConfigureAwait(false);
But anyway, remove the StartNew - you don't need this.

How to simplify or wrap exceptions when rewriting synchronous code to use TPL

Given an implementation as follows:
public class SomeServiceWrapper
{
public string GetSomeString()
{
try
{
//Do Something
}
catch (IOException e)
{
throw new ServiceWrapperException("Some Context", e);
}
catch (WebException e)
{
throw new ServiceWrapperException("Some Context", e);
}
}
}
The intention of the above is to enable the consumer of GetSomeString to only need to catch ServiceWrapperException.
Consider the following approach to extending this with a similar async behaviour:
public Task<string> GetSomeStringAsync()
{
Task<string>.Factory doSomething = ...
return doSomething.ContinueWith(x =>
{
if (x.IsFaulted)
{
if (x.Exception.InnerExceptions.Count() > 1)
{
throw new AggregateException(x.Exception);
}
var firstException = x.Exception.InnerExceptions[0];
if (typeof(firstException) == typeof(IOException)
|| typeof(firstException) == typeof(WebException))
{
throw new ServiceWrapperException("Some Context", firstException);
}
}
return x.Result;
}
}
This synchronous approach to wrapping exceptions doesn't fit naturally with the asynchronous approach.
What could the author of SomeServiceWrapper do to simplify the exception handling code of any consumers so they only need to handle TradeLoaderException instead of both IOException and WebException?
I made an extension method that pretty much does that. Usage:
public static Task<string> GetSomeStringAsync()
{
var doSomething = Task.Factory.StartNew(() => "bar");
return doSomething.WrapExceptions(typeof(IOException), typeof(WebException));
}
You can just return the original task with the continuation.
I would suggest changing ServiceWrapperException to hold more than one exception like AggregateException and then change the first part.
The Method:
public static Task<TResult> WrapExceptions<TResult>(this Task<TResult> task, params Type[] exceptionTypes)
{
return task.ContinueWith(_ =>
{
if (_.Status == TaskStatus.RanToCompletion) return _.Result;
if (_.Exception.InnerExceptions.Count > 1)
{
throw new AggregateException(_.Exception);
}
var innerException = _.Exception.InnerExceptions[0];
if (exceptionTypes.Contains(innerException.GetType()))
{
throw new ServiceWrapperException("Some Context", innerException);
}
throw _.Exception;
});
}

”Exception unhandled by user code“ when using Parallel.Invoke

I got an exception here:
MyException was unhandled by user code
In fact I have tried this, but
What is the problem and how to resolve it? What I want to achieve is get the exception be catch by the try catch surrounded the parallel.All. Now, it does not aware of that try catch, and prompt me the exception is unhandled by user code. Noted that I require the TestParallel1 method to throw exception, as this is the simplified format of the program I have. Given an exception, I wish to stop all other threads immediately. Furthermore I wish the exception propagate outside the parallel.
namespace WindowsFormsApplication1
{
static class Program
{
public static void Main()
{
try
{
List<Action> act = new List<Action>
{
()=>TestParallel1(),
() => TestParallel1()
};
Parallel.Invoke(act.ToArray());
}
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions) // note the 's' in InnerExceptions
{
//do something with 'e'
}
//do something
}
}
public class MyException : Exception
{
}
public static void TestParallel1()
{
throw new MyException();
}
}
}
You are getting the "unhandled by user code" in the debugger because you have "Just my code" setting turned on (and the original exception isn't technically being handled by your code, but rather being handled by the framework's code).
Turn off "Just my code", and you'll get a different experience.
Note, this is just debugging experience--it doesn't have any effect on the regular program flow.
See: http://msdn.microsoft.com/en-us/library/h5e30exc(v=vs.90).aspx
The Parallel members will always throw an Aggregate exception. You are catching the wrong type.
The changes you need:
//catch(MyException e)
catch (AggregateException ae)
{
foreach (var e in ae.InnerExceptions) // note the 's' in InnerExceptions
{
//do something with 'e'
}
}
To Catch this Exception and still use Parallel you could do this:
List<Action> act = new List<Action> { () => TestParallel1(),
() => TestParallel1() };
Parallel.ForEach(act, a =>{
try
{
a.Invoke();
}
catch (MyException ae)
{
//do something
}
});
EDIT
Maybe something like this could do the trick if events and delegates are ok for you
i'm aware that this code could be look better but it will show you the idea so i hope it will help you :)
public partial class MainWindow : Window
{
List<MyThread> threads = new List<MyThread>();
public MainWindow()
{
var thread1 = new MyThread();
thread1.A = () => TestParallel1();
thread1.RaisError += RaisError;
var thread2 = new MyThread();
thread2.A = () => TestParallel1();
threads.Add(thread1);
threads.Add(thread2);
Parallel.ForEach(threads, t => { t.Start(); });
}
public void RaisError()
{
Parallel.ForEach(threads, t => { t.Stop(); });
}
public static void TestParallel1()
{
throw new MyException();
}
}
public class MyException:Exception{}
public class MyThread
{
public Action A { get; set; }
public delegate void Raiser();
public event Raiser RaisError;
public void Start()
{
try
{
A.Invoke();
}
catch (MyException me)
{
RaisError();
}
}
public void Stop()
{
// do some stop
}
}
Edit 2
you may could also do this but you should read the This Answer(from Scott Chamberlain) first
List<Action> act = new List<Action> { () => TestParallel1(),
() => TestParallel1() };
Parallel.ForEach(act, (a, state) =>
{
try
{
a.Invoke();
}
catch (MyException ae)
{
state.Stop();
}
});

Repeating code pattern

I have certain code pattern (which log performance and other variable for each function) which need to be present in every function, and I do not want to repeat the code over and over again. Here is what the code looks like:
public OutClass FUNC-X
{
if (IsDebugEnabled)
{
Logger("Start DataLibrary: FUNC-X");
}
try
{
CheckInitSucceeded();
GetAuthenticationTokens();
var dm = new Manager();
/**
* THIS SINGLE LINE IS THE VARIABLE PART
**/
var output = dm.FUNC-X(...);
if (IsDebugEnabled)
{
var data = Serialize(output);
Logger(output);
}
return output;
}
catch (WebFaultException)
{
throw;
}
catch (OtherException ex)
{
if (Logger.IsErrorEnabled)
{
Logger.LogError("Exception in FUNC-X", ex);
}
throw new OtherException("Some Message");
}
catch (Exception ex)
{
if (IsErrorEnabled)
{
Logger("Exception in FUNC-X", ex);
}
throw new Exception("Generic Exception");
}
finally
{
if (IsDebugEnabled)
{
Logger("End FUNC-X");
}
}
}
Essentially, I just need to replace FUNC-X with FUNC-Y or FUNC-Z everywhere this name occurs, is there some kind of design pattern which I can follow?
I'm sorry if the question is vague, I shall be happy to provide any details you ask.
Yeah, there are many ways to provide nice log code.
Use aspect-oriented programming. There is PostSharp and Spring.NET. You can use log4net library. All of them after config supports writing of method name.
You can use T4 and generate code for all funcs before compile.
You can write one global logging method that accepts Func<object> method and string methodName. Suppose you named your logging method LogAndExecute. Then to call you must write smth like:
LogAndExecute("func-x", () => dm.Func-X(/*your args*/))
If you got problems with different different return types of your funcs, use generics
You can use simple delegate to accept the variable part as parameter (if no. of parameters to function call in single line are same)
public void Function_X(Func<object,..> func)
{
if (IsDebugEnabled)
{
Logger("Start DataLibrary: FUNC-X");
}
try
{
CheckInitSucceeded();
GetAuthenticationTokens();
var dm = new Manager();
/**
* THIS SINGLE LINE IS THE VARIABLE PART
**/
// var output = dm.FUNC-X(...);
var output = func(...);
if (IsDebugEnabled)
{
var data = Serialize(output);
Logger(output);
}
return output;
}
catch (WebFaultException)
{
throw;
}
catch (OtherException ex)
{
if (Logger.IsErrorEnabled)
{
Logger.LogError("Exception in FUNC-X", ex);
}
throw new OtherException("Some Message");
}
catch (Exception ex)
{
if (IsErrorEnabled)
{
Logger("Exception in FUNC-X", ex);
}
throw new Exception("Generic Exception");
}
finally
{
if (IsDebugEnabled)
{
Logger("End FUNC-X");
}
}
}
You can create a common function that accepts a Func delegate:
static public TOutClass CommonFunc<TOutClass>(Func<Manager, TOutClass> func)
{
if (IsDebugEnabled)
{
Logger("Start DataLibrary: FUNC-X");
}
try
{
CheckInitSucceeded();
GetAuthenticationTokens();
var dm = new Manager();
TOutClass output = func(dm);
if (IsDebugEnabled)
{
var data = Serialize(output);
Logger(output);
}
return output;
}
catch
[...]
}
Your would write your functions as:
public OutClass FUNC-X(...)
{
return CommonFunc(dm=>dm.FUNC-X(...));
}

Get thrown exception in finally block

Is there a way, how to get currently thrown exception (if exists)?
I would like reduce amount of code and apply some reuse for task looks like:
Exception thrownException = null;
try {
// some code with 3rd party classes, which can throw unexpected exceptions
}
catch( Exception exc ) {
thrownException = exc;
LogException( exc );
}
finally {
if ( null == thrownException ) {
// some code
}
else {
// some code
}
}
and replace it with this code:
using( ExceptionHelper.LogException() ) {
// some code with 3rd party classes, which can throw unexpected exceptions
}
using( new ExceptionHelper { ExceptionAction = ()=> /*some cleaning code*/ } ) {
// some code with 3rd party classes, which can throw unexpected exceptions
}
public class ExceptiohHelper : IDisposable {
public static ExceptionHelper LogException() {
return new ExceptionHelper();
}
public Action SuccessfulAction {get; set;}
public Action ExceptionAction {get; set;}
public void Dispose() {
Action action;
Exception thrownException = TheMethodIDontKnow();
if ( null != thrownException ) {
LogException( thrownException );
action = this.ExceptionAction;
}
else {
action = this.SuccessfulAction;
}
if ( null != action ) {
action();
}
}
}
Is this scenario posible?
Thanks
The idea is that you handle exceptions in the catch block...
That said, Exception is a reference type, so you can always declare an Exception variable outside the try scope...
Exception dontDoThis;
try
{
foo.DoSomething();
}
catch(Exception e)
{
dontDoThis = e;
}
finally
{
// use dontDoThis...
}
What do you think about the following. Instead of looking at the problem as "How to get the last exception?", what if you change it to, "How do I run some piece of code with some more control?"
For example:
Instead of an ExceptionHelper you could have an ActionRunner.
public class ActionRunner
{
public Action AttemptAction { get; set; }
public Action SuccessfulAction { get; set; }
public Action ExceptionAction { get; set; }
public void RunAction()
{
try
{
AttemptAction();
SuccessfulAction();
}
catch (Exception ex)
{
LogException(ex);
ExceptionAction();
}
}
private void LogException(Exception thrownException) { /* log here... */ }
}
It would at least give you some reuse of the SuccessfulAction and ExceptionAction assuming only the AttemptAction varies between calls.
var actionRunner = new ActionRunner
{
AttemptAction = () =>
{
Console.WriteLine("Going to throw...");
throw new Exception("Just throwing");
},
ExceptionAction = () => Console.WriteLine("ExceptionAction"),
SuccessfulAction = () => Console.WriteLine("SuccessfulAction"),
};
actionRunner.RunAction();
actionRunner.AttemptAction = () => Console.WriteLine("Running some other code...");
actionRunner.RunAction();
If you are looking to catch unexpected exceptions you should be handling the UnhandledException. You should only catch exceptions at lower levels that you intend handle (not just to log), otherwise you should let them bubble up and be caught at a higher level, or as I mentioned before in the UnhandledException method.

Categories

Resources