I have an anonymous TPL task with the following structure:
Task.Factory.StartNew(() =>
{
try
{
DoStuff();
}
catch (OperationCanceledException ex)
{
// process cancellation
}
catch (Exception ex)
{
// process (log) all exceptions
}
finally
{
// tie up various loose ends
}
},
myCancellationToken, // cancellation token
TaskCreationOptions.LongRunning, // always create a new thread
TaskScheduler.Default // default task scheduler
);
Inside of the DoStuff() function, I'm using Spring.NET Social extension for Dropbox to upload a large file to Dropbox. For some reason that I don't yet understand, an exception is being generating during the file upload (via the UploadFileAsync() method call):
(System.Net.Sockets.SocketException (0x80004005): An established connection was aborted by the software in your host machine).
I'm still working out why this exception is happening, but that's not the part that concerns me a present. The bigger problem is that the exception is ultimately wrapped by
System.Reflection.TargetInvocationException and for some strange reason, my try/catch block (in my original code snippet) isn't catching it.
Since I cannot catch the exception, it ultimately crashes the app.
Although I didn't think it should be necessary, I even tried adding an explicit catch block for TargetInvocationException, but again it never fires.
So my question is - how I do I catch this exception, and why isn't it being caught by the constructs shown in my code above?
UPDATE:
This problem appears to have nothing to do with the TPL after all. I modified the call to remove the call to StartNew() so that the code executes synchronously, and I still cannot catch this exception.
I used this code to verify that the TargetInvocationException can be caught:
[Test]
public void TaskExceptionTest()
{
var task = Task.Factory.StartNew(
() =>
{
try
{
throw new TargetInvocationException(null);
}
catch (Exception e)
{
Console.WriteLine("Caught one (inside):" + e.GetType().Name);
}
});
try
{
task.Wait();
}
catch (AggregateException ae)
{
// 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 ae.InnerExceptions)
{
if (e is TargetInvocationException)
{
Console.WriteLine("After:" + e.GetType().Name);
}
else
{
throw;
}
}
}
}
You can read here about exception handling and tasks.
Related
I want to set a breakpoint in my C#/Xamarin Studio project that breaks on all exceptions, EXCEPT those that have to do with task cancellation. Is that possible?
You should use separate catch for CancellationException
try
{
//do your stuff here
}
catch(CancellationException ex)
{
//behave cancellation
}
catch(Exception ex)
{
//Here handle other exceptions
//Also you can put break point here
}
If you know your entry point exactly, you could write a code like this:
try
{
....
}
catch (CancellationException)
{
throw;
}
catch (Exception ex)
{
//otherwise handle this exception
}
If not, you could catch at application domain level using the event
ApplicationDomain.UnhandledException. More details here: http://developer.xamarin.com/api/event/System.AppDomain.UnhandledException/
I think it is possible. You may add catching all exceptions listening to System.Exception. Add the condition and check the type of exception in order to skip task cancelled exceptions. Exception in the local scope is available as $exception, so the condition will look like !($exception is System.Threading.Tasks.TaskCanceledException)
I have a sync function such as the following function that generate an IO error (I delete the detail to make it simple):
public override void SyncFunction()
{
throw new IOException("test");
}
and I used it in this way:
try
{
await Task.Run(() => this.SyncFunction());
}
catch (Exception ex)
{
MessageBox.Show("Error:"+Environment.NewLine + ex.Message);
}
But when I run the application, the catch block doesn't get called, but I am getting a message that application crashed. What is the problem and how can I fix it?
The code as you described it should handle the exception just fine.
However, the thing that would crash your application is an exception thrown inside an async void method as the exception has no Task to be stored inside.
So, my guess is that SyncFunction actually looks more like this:
public override async void SyncFunction()
{
throw new IOException("test");
}
And when you invoke it the exception is posted to a ThreadPool thread and that crashes the application.
If that's the case, don't use async void unless in a UI event handler and make sure you handle such exceptions by registering to the AppDomain.CurrentDomain.UnhandledException event.
ReSharper was giving me a CoVariantConversion warning so I decided to google this and see how to fix it. I came accross this snippet of code:
// ReSharper disable CoVariantArrayConversion
try
{
Task.WaitAll(taskList.ToArray());
}
catch (AggregateException ex)
{
ex.Handle(e => true);
}
// ReSharper restore CoVariantArrayConversion
This part is confusing me:
ex.Handle(e => true);
What does it do? I would think that it does nothing.
You are correct: the line can be removed and have the same effect (causing all the exceptions to be considered "handled") as if the line was there.
The only time it would be useful is if the lambda could return false for some exceptions (which it doesn't in this case).
This say, that the Exception is handled, nothing else.
Here is a sample that Shows how the Handle method could be used:
Task task = Task.Factory.StartNew(() =>
{
throw new UnauthorizedAccessException();
});
try
{
task.Wait();
}
catch (AggregateException ex)
{
ex.Handle(x =>
{
if (x is UnauthorizedAccessException)
{
// Handle this exception...
return true;
}
// Other exceptions will not be handled here.
return false;
});
}
The sample comes from this article: Asynchronous Programming - Exception Handling
I have a try..catch block that looks like this:
try
{
...
}
catch (IOException ioEx)
{
...
}
catch (Exception ex)
{
...
}
I'd like to handle just a certain kind of IOException, namely a sharing violation (Win32 0x20). Other IOExceptions and all other Exception descendants should be handled generally by the second catch-all catch.
Once I know that the IOException is not a sharing violation, how can I cleanly redirect the error handling flow to the general catch? If I rethrow in catch (IOException) the second catch does not invoke. I know I can nest try..catches but is there a cleaner way?
EDIT: On factoring-out handler logic
Factoring repeated code in methods will surely work, but I noticed that in general when you use factored methods for exception handling it tends to have subtle problems.
First of all, a catch clause has direct access to all of the local variables prior to the exception. But when you "outsource" exception handling to a different method then you have to pass the state to it. And when you change the code so does the handler method's signature changes, which might be a maintainability issue in more complicated scenarios.
The other problem is that program flow might be obscured. For example, if the handler method eventually rethrows the exception, the C# compiler and code analyzers like Resharper don't see it:
private void Foo()
{
string a = null;
try
{
a = Path.GetDirectoryName(a);
System.Diagnostics.Debug.Print(a);
}
catch (Exception ex)
{
HandleException(ex, a); //Note that we have to pass the "a"
System.Diagnostics.Debug.Print(
"We never get here and it's not obvious" +
"until you read and understand HandleException"
);
...!
}
}
static void HandleException(Exception ex, string a)
{
if (a != null)
System.Diagnostics.Debug.Print("[a] was not null");
throw (ex); //Rethrow so that the application-level handler catches and logs it
}
VS
private void Bar()
{
string a = null;
try
{
a = System.IO.Path.GetDirectoryName(a);
System.Diagnostics.Debug.Print(a);
}
catch (Exception ex)
{
if (a != null)
System.Diagnostics.Debug.Print("[a] was not null");
throw; //Rethrow so that the application-level handler catches and logs it
System.Diagnostics.Debug.Print(
"We never get here also, but now " +
"it's obvious and the compiler complains"
);
...!
}
}
If I want to avoid these kind of (minor) problems then it seems that there is no cleaner way than nesting try..catch blocks, as Hank pointed out.
Just factor the handling logic into a separate method.
try
{
...
}
catch (IOException ioEx)
{
if (sharing violation)
HandleSharingViolation();
else
HandleNonsharingViolation();
}
catch (Exception ex)
{
HandleNonsharingViolation();
}
Or test the exceptions yourself
catch (Exception ex)
{
if (ex is IOException && ex.IsSharingViolation()
HandleSharingViolation();
else
HandleNonsharingViolation();
}
No, you'll have to nest.
Once you are in 1 of the catch blocks, this 'try' is considered handled.
And I think it may make a lot of sense, "sharing violation" sounds like a special case that probably isn't so tightly coupled to the rest as you might be thinking. If you use nest try-catch, does the try block of the special case has to surround the exact same code? And of course it's a candidate to refactor out as a separate method.
Create Method to handle exception, pass the exception to that method , based on the type Handle the exception in the way you want.Call these method in both these blocks.
Use nested try catch blocks.
try
{
try
{
}
catch (IOException ioEx)
{
if (....)
else
throw;
}
}
catch
{
}
what about "finally"?
you can first set a 'variable' in the IOException block once you know the IOException is not sharing violation. Then, in your finally block, if that 'variable' is set, you proceed to do whatever you need to do.
Below impl. tested and confirmed.
bool booleanValue = false;
try
{
test1(); // this would thro IOException
}
catch (IOException e)
{
booleanValue = true; // whatever you need to do next
}
finally
{
if (booleanValue)
{
Console.WriteLine("Here");
}
}
Tryout this nested block
try
{
}
catch(Exception ioex)
{
try
{
}
catch(Exception ex)
{
}
}
I am confused about the order of try, catch and finally block execution.
I also want to know when should I use try-catch block and what should I put in the try-catch block?
I also want to know if some exception comes in try block then if an action is taken corresponding to try block then which one is executed first catch or finally (which is always to be executed)?
After the execution of these two does control return to try block or it leave it?
If you have (note: this is not valid C#, see below for a valid example):
try {
// ... some code: A
} catch(...) {
// ... exception code: B
} finally {
// finally code: C
}
Code A is going to be executed. If all goes well (i.e. no exceptions get thrown while A is executing), it is going to go to finally, so code C is going to be executed. If an exception is thrown while A is executed, then it will go to B and then finally to C.
As an example, here's a valid C# code block from http://msdn.microsoft.com/en-us/library/dszsf989.aspx:
public class EHClass
{
void ReadFile(int index)
{
// To run this code, substitute a valid path from your local machine
string path = #"c:\users\public\test.txt";
System.IO.StreamReader file = new System.IO.StreamReader(path);
char[] buffer = new char[10];
try
{
file.ReadBlock(buffer, index, buffer.Length);
}
catch (System.IO.IOException e)
{
Console.WriteLine("Error reading from {0}. Message = {1}", path, e.Message);
}
finally
{
if (file != null)
{
file.Close();
}
}
// Do something with buffer...
}
}
The reason to use try/catch/finally is to prevent your program to fail if there is an error in some code (A in the above example). If there is a problem, you can use catch part to catch the problem and do something useful, such as inform the user, log the exception to a log file, try again or try something different that you suppose might work instead of what you tried originally.
finally is used to ensure that some cleanup is performed. E.g. in A you might try to open a file and read it. If opening succeeds, but read fails, you will have an open file dangling. What you would like in that case is to have it closed, which you would do in finally block - this block always gets executed, guaranteeing the closing of the file.
Take a look here for more info:
http://msdn.microsoft.com/en-us/library/0yd65esw.aspx
http://www.c-sharpcorner.com/UploadFile/puranindia/75/Default.aspx
A try ... catch block is used to catch exceptions. In the try block you put the code that you expect may raise an exception.
If no exception occurs then the code in the try block completes as expected. If there's a finally block then that will execute next.
If an exception does occur then execution jumps to the start of the first matching catch block. Once that code is complete the finally block (if it exists) is executed. Execution does not return to the try block.
You should almost never use try/catch.
You should only catch exceptions that you can actually correct, and only when you're expecting them. Otherwise, let the caller handle the exception - or not.
If used, any catch clauses are executed first - only one of them.
Then, finally is "finally" executed.
This has been stated better in many places, but I'll try. The following code:
try
{
// Do something here
}
catch (Exception ex)
{
MessageBox.Show("Friendly error message");
}
does not fix the exception. It hides the exception so that the problem will never be fixed. That code has no idea which exception was thrown, because it will catch all of them, and it does nothing to correct the problem - it just tells the user a polite fiction.
The fact of the matter is that the code above should be replaced with the following:
// Do something here
This way, if the caller of this method knows how to fix particular problems, then the caller can fix them. You will not have removed that option from the caller.
If the caller does not know how to fix the problem, then the caller should also not catch the exception.
Here is an example (from MSDN) of using exceptions in a reasonable manner. It's a modified form of the example in the documentation of the SmtpFailedRecipientsException Class.
public static void RetryIfBusy(string server)
{
MailAddress from = new MailAddress("ben#contoso.com");
MailAddress to = new MailAddress("jane#contoso.com");
using (
MailMessage message = new MailMessage(from, to)
{
Subject = "Using the SmtpClient class.",
Body =
#"Using this feature, you can send an e-mail message from an application very easily."
})
{
message.CC.Add(new MailAddress("Notifications#contoso.com"));
using (SmtpClient client = new SmtpClient(server) {Credentials = CredentialCache.DefaultNetworkCredentials})
{
Console.WriteLine("Sending an e-mail message to {0} using the SMTP host {1}.", to.Address, client.Host);
try
{
client.Send(message);
}
catch (SmtpFailedRecipientsException ex)
{
foreach (var t in ex.InnerExceptions)
{
var status = t.StatusCode;
if (status == SmtpStatusCode.MailboxBusy || status == SmtpStatusCode.MailboxUnavailable)
{
Console.WriteLine("Delivery failed - retrying in 5 seconds.");
System.Threading.Thread.Sleep(5000); // Use better retry logic than this!
client.Send(message);
}
else
{
Console.WriteLine("Failed to deliver message to {0}", t.FailedRecipient);
// Do something better to log the exception
}
}
}
catch (SmtpException ex)
{
// Here, if you know what to do about particular SMTP status codes,
// you can look in ex.StatusCode to decide how to handle this exception
// Otherwise, in here, you at least know there was an email problem
}
// Note that no other, less specific exceptions are caught here, since we don't know
// what do do about them
}
}
}
Note that this code uses try/catch to surround a small piece of code. Within that try/catch block, if an SmtpException or SmtpFailedRecipientsException is thrown, we know what to do about it. If, for instance, we were to catch IOException, we would not know what it meant, or what to do about it. Any exception you don't actually know how to correct should not be caught, except maybe to add information to the exception, log it, and rethrow.
Here is an example:
try
{
someFunctionThatWorks();
functionThatThrowsAnException(); // As soon as this function throws an exception we are taken to the catch block
anotherFunction(); // <-- This line will never get executed
}
catch(Exception e)
{
// Here you can handle the exception, if you don't know how to handle it you should not be catching it
// After this you will not be taken back to the try block, you will go right to the finally block
}
finally
{
// Code here is always executed at the very end, regardless of whether an exception was thrown or not
}
I'd like to elaborate a bit on this and extend #icyrock.com answer with scenario when you rethrow the exception in the catch block so it is handled lower on the execution stack...
I gave it a try with the following code:
static void Main(string[] args)
{
try
{
// pick one:
// NormalExcecution();
// TroubleExcecution();
}
catch
{
Console.WriteLine("block D");
}
Console.ReadKey();
}
private static void NormalExcecution()
{
try
{
Console.WriteLine("block A");
}
catch (Exception)
{
Console.WriteLine("block B");
throw;
}
finally
{
Console.WriteLine("block C");
}
}
private static void TroubleExcecution()
{
try
{
Console.WriteLine("block A");
throw new Exception();
}
catch (Exception)
{
Console.WriteLine("block B");
throw;
}
finally
{
Console.WriteLine("block C");
}
}
So when there is no exception in block A, then the sequence is as follows (exception handling blocks are never hit):
Block A
Block C
When there's some problem with block A, the sequence is as follows:
block A
block B
block C
block D
Another words, the occurring exception is first handled by block B, then the finally clause is executed, only after that the exception is rethrown and handled lower on the execution stack (block D).
Please mind I may be wrong with what is actually going on under the hood of the .NET framework - I just present the results I observed :)