Let say I have an async method:
public async Task Do()
{
await Task.Delay(1000);
}
Another method is trying to call Do method inside catch block
public async Task DoMore()
{
try
{
}
catch (Exception)
{
await Do(); //compiled error.
}
}
But this way, the compiler does not allow using await inside catch, is there any reason behind the scene why we could not use it that way?
Update
This will be supported in C# 6. It turned out that it wasn't fundamentally impossible, and the team worked out how to do so without going mad in the implementation :)
Original answer
I strongly suspect it's the same reasoning that prevents yield return from being used in a catch block.
In particular:
First off, we still have the problem that it is illegal to "goto" into the middle of the handler of a try-protected region. The only way to enter a catch block is via the "non-local goto" that is catching an exception. So once you yielded out of the catch block, the next time MoveNext was called, we’d have no way to get back into the catch block where we left off.
Second, the exception that was thrown and caught is an intrinsic part of the execution of the catch block because it can be re-thrown using the "empty throw" syntax. We have no way of preserving that state across calls to MoveNext.
Replace "yield" with "await" there, and I think you'll have your answer.
It feels like it would be an odd thing to want to do in most cases, and you should usually be able to rewrite your code fairly easily to await after the catch block - unless you were trying to await something and then throw, of course. In that case it would be a bit of a pain, I admit...
Related
I am trying to create a type of "fire and forget" function where I don't care about the completion or the result of the function. In order to do that I am using Task.Run() in the body of that function so I can run it concurrently and return from it right away.
I think its important to mention that this runs is a IIS application.
Something like this:
void ReallyImportantFunction()
{
//Do really important work
NotSoImportantWork("some data");
//Do really important work
}
void NotSoImportantWork(string data)
{
Task.Run(() =>
{
try
{
//Do something here with the data
}
catch (Exception ex)
{
//Log exception do not throw
}
});
}
It's hard to answer this question without a bit more information, but I think you're misunderstanding the use of Task.Run() and asynchronous code. If it's unimportant work, and you don't care about the result or its completion, you might ask if you need to be running it here in the first place. Secondly, Task.Run() is typically used in order to execute long-running code that might otherwise block the UI thread. If you're making a DB call or writing to the File System, it could make sense to put this logic in a Task. An example being
void ReallyImportantFunction()
{
try
{
//Do really important work
Task.Run(() => NotSoImportantWork("some data"));
//Do really important work
}
catch (Exception ex)
{
/ Handle the exception
}
}
void NotSoImportantWork(string data)
{
//Do something here with the data
}
However this exposes you to data races if you actually do ever use whatever you're computing, or if your computation ever has any side-effects or mutations. If what you're saying is true and you never do look at the result, I would probably ask why it's in the method to begin with. Why compute really unimportant things right in the middle of important ones if you're never going to use them? If you are using the result, or mutating something you need, it makes sense for your code to properly await the result.
async void ReallyImportantFunction()
{
try
{
//Do really important work
var myResult = await IOIntensiveWork("some data");
//Do really important work
}
catch (Exception ex)
{
// Handle the exception
}
}
Task<MyResult> IOIntensiveWork(string data)
{
//Do something here with the data
}
It's usually cleaner if you can avoid async void methods too, though there's nothing necessarily wrong with it. Just remember to always check for exceptions.
Edit: Based on what you've written in the comments, I think it makes sense to wrap your NotSoImportantWork() in a task. This is not so much because it is unimportant, but rather because you are apparently making a network call, and there are a variety of problems that can occur while communicating with a service outside your control.
So you could just Task.Run(() => NotSoImportantWork("...")); from ReallyImportantFunction(), but be mindful of where you're catching exceptions and where your code potentially exits if one should occur. I would probably prefer to launch the Task.Run() there rather than in NotSoImportantWork(), because you could potentially use Task.Run(...).ConfigureAwait(false); to squeeze that last bit of performance out of your code (this largely depends on how your code is structured).
Depending on where you're launching your task from, you can use ...ConfigureAwait(false); to say that you don't need to the task to return to the current context when the operation completes. This can sometimes give performance improvements. Try and use it whenever it makes sense. For more information, have a look at this: When correctly use Task.Run and when just async-await
Without more of a context to your code, it's hard to go into much more detail than this. Hope it helps!
This question already has answers here:
Is finally block in C# a must?
(7 answers)
Closed 1 year ago.
If I catch all exceptions;
try
{
... //code causes error
}
catch (Exception e)
{
...//handle all exceptions
}
So there is no need to use Finally block? since I catch all exceptions, the program will continue to execute the code after try-catch?
Another questions is, if use a finally block, how can I catch the errors happened in the final block itself? I mean it looks like we only need to put everything in the try and catch block which is in the very end?
So there is no need to use Finally block?
The finally clause has very little to do with what, how and how many exceptions you catch. Think of the code that goes in a finally clause as clean up code that must be run independently of what happens inside the try clause. A typical scenario is the following (I'll use some C#7 for the fun of it):
(bool Succesful, object Result) TryDoSomethingDangerous()
{
var someDisposableObject = new SomeDisposableObject();
try
{
var result = someDisposableObject.DoSomethingDangerous(); //documented to be able to throw SomethingBadHappenedException
return (true, result);
}
catch (SomethingBadHappenedException e)
{
Logger.Log(e);
InformUserSomethingWentWrong(e);
return (false, null);
}
finally
{
someDisposableObject.Dispose();
}
}
since I catch all exceptions, the program will continue to execute the code after try-catch?
This is worrying. Yes if you catch all exceptions your code will keep running (how long is anyone's guess), but this is, in general, a very bad idea. You should only deal with exceptions you know how to fix and recover from. Swallowing exceptions just to keep trudging along is bound to end in disaster.
In general, catch (System.Exception) is a bad idea unless you are planning to simply log information and re throw immediately.
Another questions is, if use a finally block, how can I catch the errors happened in the final block itself? I mean it looks like we only need to put everything in the try and catch block which is in the very end?
Again, you are completely misunderstanding the execution flow in try-catch-finally. Code in finally is code that must run no matter what happens inside the try clause. You seem to believe that it's code that should only run if there is an exception.
In general, its better if code inside a finally clause is robust and does not throw exceptions itself. If, given the circumstances, this is not possible then the code inside the finally clause will need to have its own exception handling mechanism. In my case I try to avoid this kind of scenario and refactor code accordingly.
In situations such as releasing resources, it is used twice instead of writing the same code (both try and catch). Such as closing the database connection and disposing of an object
Let's suppose I have the following code...
try
{
await Task.Run(() => autobuyandsell.Discard_Players(client, this));
if (stop == false)
{
await Task.Run(() => autobuyandsell.Buy_300_Players(client, this));
}
}
catch (ExpiredSessionException ex)
{
relogin = true;
b_stop.PerformClick();
}
Inside autobuyandsell the ExpiredSessionException can occur as I call some methods which can throw that Exception. My question is, do I need to add another try/catch block inside the function or it's enough to handle the extern Exception?
Answer accepted:
As the only need of my program is to exit the method and restart some variables, eventually, I decided to use try/catch outside the method.
You will catch them as you have it just now but you won't "know" if/how much of your Discard_Players or buy_300_Players code executed, and at which point the Exception occurred, etc. which may be a bad idea.
For example if these methods persist state to disk/database you wont "know" if this happened or not.
(I keep using the quotes on "know" because I guess it would be possible to interrogate the call stack etc when catching the Exception to find out where it was raised in order to find these things out but that's going to get messy pretty quickly!)
if you catch them INSIDE the methods you can control how they are handled (perhaps undoing any data you have persisted before throwing again so you can start afresh, for example) much better.
So depending on the functionality of these two functions YOU should decide which approach works best for YOUR application
When throwing exceptions between multiple methods, should all methods re-throw the exception? for example
Method1()
{
Method2();
}
Method2()
{
try
{
// Do something
}
catch
{
throw;
}
}
try
{
Method1();
}
catch
{
// Do something about exception that was thrown from Method2()
}
Notice how in Method1(), I didn't need to wrap Method2() in a try block, should I be?
You don't need to wrap everything in try blocks.
You should only try when you want to catch something, and you should only catch something in the following cases:
You're ready to handle the exception (do whatever needs to be done and don't let it propagate up the stack),
You want to do something with the exception (e.g. log it) before rethrowing it (by using the parameterless form of throw),
You want to add details to the exception by wrapping it in another exception of your own (see Allon Guralnek's excellent comment below).
You do not need to try, catch, and rethrow exceptions unless you have some particular reason for catching them in the first place. Otherwise, they'll automatically get bubbled up from the lower level functions that throw them to the highest level function in your code. Essentially, you can think of them as getting "rethrown" all the way up, even though this isn't technically what is happening.
In fact, most of the time that you see a try/catch block written, it's incorrect. You should not catch exceptions unless you can actually handle them. It's utterly pointless (and in fact considered to be bad practice) to catch exceptions just to rethrow them. Do not wrap all of your code within try blocks.
Note that by "handle them", I mean that your code in the catch block will take some specific action based on the particular exception that was thrown that attempts to correct the exceptional condition.
For example, for a FileNotFoundException, you might inform the user that the file could not be found and ask them to choose another one.
See my answer here for more detail and a thorough discussion of "exception handling best practices".
Consider the following C# code structure (S0-S3 are placeholders for arbitrary code blocks):
try
{
S0;
}
catch (Exception ex)
{
S1;
}
finally
{
S2;
}
S3;
In the case that S1 throws an exception inside the catch handler, S2 inside the finally will still execute (but S3 will not).
Question
Assuming that S1 cannot throw, is there any point in having S2 inside a finally block, rather than having it outside the try/catch/finally, just before S3?
Example
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
finally
{
S2;
}
S3;
Is there any point in having the finally block? Would the following code not be equivalent (under the strict assumption that what's inside the catch block cannot throw):
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
// No finally block needed (?)
S2;
S3;
Secondary Question
Update: If it is accepted that the two code blocks above are equivalent (under the assumptions stated) then, taking into account the feedback on code clarity in the answers, would it be preferrable (and equivalent) to combine S2 and S3 inside the finally block?
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
this.cachedException = ex;
}
finally
{
S2; // Put S2 and S3 together inside the `finally` block to guard against
S3; // future changes in the `catch` filter, or handling code.
}
The assumption that S1 cannot throw is a fragile one, considering resource depletion scenarios (i.e., you run out of memory). Even if warranted (a big if), minor changes to the code can introduce an exception.
Since S2 is usually concerned with cleaning up and releasing valuable resources, putting it in a finally block communicates that intention clearly. Putting such code, where possible, in a Dispose() method of a resource owning object and replacing the try/finally clause with a using clause can communicate the intention even better (and more idiomatically for C#).
Whenever you can write something in two or more different ways, use the one that is clearest and most stable against changes.
Re the secondary question: S3 should be placed inside the finally if it's concerned with cleanup. If it presupposes the success of the try block, it should be placed after the finally block. If your catch statement doesn't rethrow, I personally would interpret it to mean that you have succeeded and can proceed with normal operations. However, the whole 'Save the exception to re-throw later' thing confuses me. Generally, I'd advise against storing an exception for rethrowing outside the method. It's unusual and seems confusing to me. The fewer surprises your code contains, the easier it is to maintain (including yourself, three months later).
One case where you might not anticipate S1 throwing: if the thread is interrupted, the exception will automatically be rethrown at the end of the catch block anyway.
As Pontus says, a finally block indicates the intention that this code should always be run whatever happens. That's clearer than catching everything and then continuing.
finally block is used to do resource clean up either exception happens or not, finally block will both be called, so it's ideal place to do cleanup work.
I think this is similar to putting brackets around if statement contents.
While you could argue that
if (x) y;
will not fail, whats to say that some less experienced programmer will not come along later and edit it to
if (x) y; z;
It may be the case that the finally block is not necessary for your code as it stands, but it is always a good idea to leave it in in case the code in the catch block ever changes.
if (x)
{
y;
}
always wins for me.
Note that the finally clause is executed even if the try or catch block contains a return statement.
In your particular case there is no difference..
But if do you did not catch Exception, but rather some specific subclass of Exception then there would be a difference. And that is probably the normal pattern when looking at a try-catch-finally block.
You might be able to ensure your code doesn't throw an Exception today, but what about when you come back to it in 6 months time? Or someone else has to make changes?
Using a finally block is a recognised pattern that will make sense to any programmer, if your code does something special and different, it will trip you or someone else up.
In second case, control will only reach S2 surely if you swallow any exception ever caught in catch block! Try-Catch should not be use here-and-there but carefully.
Ex:
try
{
// Do something that might throw
}
catch (Exception ex)
{
// Save the exception to re-throw later
// NB: This statement cannot throw an exception!
// this.cachedException = ex;
// Must swallow any exception here to let control go further!
// If you're not sure enough [which you and me both are not likely to be] - use finally to execute S2 in any condition
}
// No finally block needed (?)
S2;
S3;
To guarantee resources are cleaned up when an exception occurs, use a try/finally block. Close the resources in the finally clause. Using a try/finally block ensures that resources are disposed even if an exception occurs....For further details check http://itpian.com/Coding/5143-Need-for-Finally-block.aspx
No you dont have to use it. Its not required in that case. Its a choice for you and depends on the resources you may/may not be using. If you need to cleanup any resources you might have then the finally block is the best option.