Are exceptions thread-safe? - c#

I wonder what happens if I catch an exception and pass it to some other threads.
try
{
//...
}
catch (Exception e)
{
for (int i = 0; i < 100; i++)
{
int currIndex = i;
Task.Run(() => e.Data[currIndex] = currIndex);
}
throw;
}
Given these other threads alter the contents of the exception's Data property (that holds an internal dictionary, see Reference Source), will the Datadictionary get corrupted?
Looking into the source code of Exception reveals that this dictionary is not thread-safe.
If my suspicion is true, what are the consequences? I would think that you should never alter the contents of the Data property after throwing the exception, right?

Related

Is this good practice?

I have this extension method that allows me to retry an operation if there is an exception, a typical use is trying to write to a file, but for some reason I can't so I retry a bit later...
The extension looks like:
public static void WithRetry<T>(this Action action, int timeToWait = 500, int timesToRetry = 3) where T : Exception
{
int retryCount = 0;
bool successful = false;
do
{
try
{
action();
successful = true;
}
catch (T)
{
retryCount++;
Thread.Sleep(timeToWait);
if (retryCount == timesToRetry) throw;
}
catch (Exception)
{
throw;
}
} while (retryCount < timesToRetry && !successful);
}
Visual studio tells me that I'm swallowing an exception in the first catch block, is this bad?
Thanks.
The warning is exactly what you are trying to achieve. You are swallowing the exceptions (timesToRetry-1) times. On the last try only you are actually throwing the exception. Until then all the exceptions will be swallowed and lost. Since this is the behavior you are trying to achieve. There is no harm in suppressing the message.
But as #HimBromBeere stated remove the catch(Exception) block. Also you can try logging the exception on each re-try because you will loose this data. What if different kind of exception is thrown each time. There is no way to be sure.
The warning is correct, you swallow exceptions. If you retry 10 times you will never know what went wrong the first 9 times, you only get exception number 10.
Maybe that's what you want. Personally, I would put all the occurring exceptions into an AggregateException and throw that when you hit your retry count.
Maybe like this:
public static void WithRetry<T>(this Action action, int timeToWait = 500, int timesToRetry = 3) where T : Exception
{
var exceptions = new List<Exception>();
for (int tryIndex = 0; tryIndex < timesToRetry; tryIndex++)
{
try
{
action();
return;
}
catch (T t)
{
exceptions.Add(t);
}
Thread.Sleep(timeToWait);
}
throw new AggregateException(exceptions);
}

Which one is Safer? Putting An "for" in a "Try" , or putting a "Try" in An "for"?

I have this piece of code, I want to know do they work likewise and only their speed is different or they act totally different?
try
{
for (int i = Start; i < End; i++)
{
src.Samples[i].x = i;
src.Samples[i].y = HR[i];
}
}
catch{}
or
for (int i = Start; i < End; i++)
{
try
{
src.Samples[i].x = i;
src.Samples[i].y = HR[i];
}
catch
{
break;
}
}
Just don't do that to start with - it's an abuse of exceptions, IMO. Write the code so it's safe without try/catch. If you don't know whether HR is long enough, use:
int cappedEnd = Math.Min(HR.Length, End);
for (int i = Start; i < cappedEnd; i++)
{
src.Samples[i].x = i;
src.Samples[i].y = HR[i];
}
(Use similar logic for Start if that might be invalid.)
If you feel you absolutely have to use try/catch for some reason, I'd catch the exact type you're expecting to be thrown, and put it on the outside of the loop - catching just to break feels even worse to me. And no, I wouldn't expect any significant performance difference either way.
The main difference would be that encapsulating your logic in a try statement would enable you to catch any errors/exceptions that might occur.
In your second listed example your could get an exception because of Start and or End being invalid values for some reason or the other causing a crash that you wouldn't catch.
Note that most code of that level is usually very simple and not very error prone.
Writing code that is free of exceptions is often the better approach though.
As stated in the comments you would need a catch block in your first example for it to work though.
I hopes you are a beginer(like me), so you expects an answer like this
I will tell another example.
first code
try{
foreach(file in files)
{
upload(file);
}
}
catch(Exception ex)
{
handleException(ex);
}
second code
foreach(file in files)
{
try{
upload(file);
}
catch(Exception ex)
{
handleException(ex);
}
}
on first code all file upload will stop when first one fails. In second if one failes handles exception there itself and code continues for next execution.
So in the example you given both seems like works in same way(since you are giving in break in catch block. Other wise both are differnet). So use try catch where it really requires handling.

.NET error handling

I have been writing .NET applications and have been impressed with the error handling included in the framework.
When catching an error that has been throw by the processes or somewhere in the code I like to include the message (ex.Message, which is usually pretty general) but also the stacktrace (ex.stacktrace) which helps to trace the problem back to a specific spot.
For a simple example let's say for instance that we are recording numbers to a log in a method:
public void ExampleMethod(int number){
try{
int num = number
...open connection to file
...write number to file
}
catch(Exception ex){
.... deal with exception (ex.message,ex.stacktrace etc...)
}
finally{
...close file connection
}
}
Is there any way to see the method called (in this case ExampleMethod) with the specific number that was passed that potentially crashed the method call? I believe you could log this perhaps in the catch block but I am interested essentially in catching the method call and parameters that caused the system to throw the exception.
Any ideas?
I suggest stuffing the parameter values into the exception's Data dictionary, e.g.
public void ExampleMethod(int number) {
try {
int num = number
...open connection to file
...write number to file
}
catch(Exception ex) {
ex.Data["number"] = number;
//.... deal with exception (ex.message,ex.stacktrace etc...)
}
finally {
//...close file connection
}
Another advantage of this method is that you can stuff the parameters in the catch block, then re-throw the exception and log it somewhere else without losing the stack trace, e.g.
catch(Exception ex) {
ex.Data["number"] = number;
throw;
}
If you want to know the value of the parameters in your method, then there is only one way, IMO, to do it - you need to repackage the exception with data.
For example:
int param1 = 10;
string param2 = "Hello World";
try
{
SomeMethod(param1, param2)
}
catch(SomeExpectedException e)
{
throw new MyParameterSensitiveException(e, param1, param2);
}
You basically repackage the original exception as the inner exception of another exception, and additionally supply the parameters you used to call the method. Then you could inspect that in some way to figure out what went wrong.
The accepted answer and many of the solutions described will work fine but what you're doing is littering your source with a slightly different blob of code depending on what parameters are in your method signature.
When it comes time to add a new parameter you need to remember to update your handler to add that new parameter. Or if you remove a parameter then you need to remember to remove the parameter from your exception handler.
What if you have a two or more try..catch blocks? Then you now have two blocks of code to keep up to date. Definitely not refactor friendly.
Another approach is to remove the logging code use a technique called Aspect Oriented Programming.
One such tool to facilitate this is a product called PostSharp.
With PostSharp you can write a logger than is invoked whenever an exception is thrown without the need for messy method and parameter specific code. For example (using version 1.5 of PostSharp):
LoggerAttribute.cs -
[Serializable]
public class LoggerAttribute : OnExceptionAspect
{
public override void OnException(MethodExecutionEventArgs eventArgs)
{
Console.WriteLine(eventArgs.Method.DeclaringType.Name);
Console.WriteLine(eventArgs.Method.Name);
Console.WriteLine(eventArgs.Exception.StackTrace);
ParameterInfo[] parameterInfos = eventArgs.Method.GetParameters();
object[] paramValues = eventArgs.GetReadOnlyArgumentArray();
for (int i = 0; i < parameterInfos.Length; i++)
{
Console.WriteLine(parameterInfos[i].Name + "=" + paramValues[i]);
}
eventArgs.FlowBehavior = FlowBehavior.Default;
}
}
You then decorate your classes with the LoggerAttribute:
[Logger]
public class MyClass
{
public void MyMethod(int x, string name)
{
// Something that throws an exception
}
}
Anything that throws an exception in MyMethod will cause the OnException method to be executed.
There are two versions of PostSharp. Version 1.5 is free and open sourced under the GPL and is targeted at .NET 2.0. PostSharp 2.0 is not entirely free but its community edition will support the basic functionality described above.
In order to do this:
public void MyProblematicMethod(int id, string name)
{
try
{
object o = null;
int hash = o.GetHashCode(); // throws NullReferenceException
}
catch (Exception ex)
{
string errorMessage = SummarizeMethodCall(MethodBase.GetCurrentMethod(), id, name);
// TODO: do something with errorMessage
}
}
...and get this:
"MyProblematicMethod invoked: id = 1, name = Charlie"
...you could do something like this:
public static string SummarizeMethodCall(MethodBase method, params object[] values)
{
var output = new StringBuilder(method.Name + " invoked: ");
ParameterInfo[] parameters = method.GetParameters();
for (int i = 0; i < parameters.Length; i++)
{
output.AppendFormat("{0} = {1}",
parameters[i].Name,
i >= values.Length ? "<empty>" : values[i]
);
if (i < parameters.Length - 1)
output.Append(", ");
}
return output.ToString();
}
You could make a class that inherits Exception and add some arguments to it so you could pass the number to it.
You can get the method name and the parameters like this,
try
{
int a = 0;
int i = 1 / a;
}
catch (Exception exception)
{
StackTrace s = new StackTrace(exception);
StackFrame stackFrame = s.GetFrame(s.FrameCount - 1);
if (stackFrame != null)
{
StringBuilder stackBuilder = new StringBuilder();
MethodBase method = stackFrame.GetMethod();
stackBuilder.AppendFormat("Method Name = {0}{1}Parameters:{1}", method.Name, Environment.NewLine);
foreach (ParameterInfo parameter in method.GetParameters())
{
stackBuilder.AppendFormat("{0} {1}", parameter.ParameterType.FullName, parameter.Name);
stackBuilder.AppendLine();
}
// or use this to get the value
//stackBuilder.AppendLine("param1 = " + param1);
//stackBuilder.AppendLine("param2 = " + param2);
}
}
I am not sure whether you can get the parameter values directly off the stack like a debugger.
The Automatic Exception Handling from Crypto Obfuscator can do what you need.
The exception reports include all pertinent information including full stack trace info along with the values of all method arguments and local variables, plus the system information, the time of the exception, the build number, and optional developer defined custom data like log files, screenshots, etc.
DISCLAIMER: I work for LogicNP Software, the developer of Crypto Obfuscator.

handling exceptions on tasks on .net 4.0

I'm getting an odd exception on task creation in .net 4.0.
I'm getting the exception on windows service with a Global Updomain unhandled exceptions handler so I don't have the exact stack: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property.
I think it occurs on the following code section:
for (int i = 0; i < _workers.Length; ++i)
{
int j = i; // copy
Task t1 = Task.Factory.StartNew(() =>
{
try
{
if (!_workers[j].Join(4000))
LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose");
}
catch (Exception ex)
{
OnLogged(ex.Message + ex.StackTrace);
}
});
}
Anyone got an idea? Is it something with the aggregated exception feature?
See the bottom of
http://blogs.msdn.com/b/pfxteam/archive/2009/10/27/9913610.aspx
for some useful info.
I don't think this is coming from the code you have showed in the question.
You should find the exception is of type AggregateException (for future reference include the exception type when asking questions—it is key information).
This includes the exceptions thrown in its InnerExceptions property.
well, I think that Task should catch AggregateExecption when using Parallel.For\Foreach as follows:
try
{
Parallel.For(0, _workers.Length, i =>
{
DoWork(i);
});
}
catch (AggregateException ex)
{
// Assume we know what's going on with this particular exception.
// Rethrow anything else. AggregateException.Handle provides
// another way to express this. See later example.
foreach (var e in ex.InnerExceptions)
{
OnLogged(e.Message + e.StackTrace);
}
}

Does DataRow throw an InvalidCastException when I insert a value of a different type...?

I'm trying to catch an Exception when an invalid value gets stored into a DataRow. I'm reading the values from a text file so anything could be stored there. I was hoping to be able to catch an InvalidCastException from the following code...
try
{
// Store the values into the Data Row
DataRow row = dataset.Tables["Table"].NewRow();
for (int i = 0; i < fieldCount; i++)
row[i] = values[i];
dataset.Tables["Table"].Rows.Add(row);
}
catch (InvalidCastException castException)
{
return false; // Not a serious problem...just log the issue
}
catch (Exception e)
{
throw e; // A more serious problem occured, so re-throw the exception
}
The problem seems that storing an invalid value into the DataRow (storing "Hello" into a column defined for ints) throws a general exception (System.Exception) so doesn't get caught by my try/catch block...wasn't sure if that's in line with the MSDN documentation.
OK...worked it out...
It throws an ArgumentException.

Categories