Here Microsoft says:
"By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block."
and clearly use this sample to support that idea:
public class ThrowTestA
{
static void Main()
{
int i = 123;
string s = "Some string";
object obj = s;
try
{
// Invalid conversion; obj contains a string, not a numeric type.
i = (int)obj;
// The following statement is not run.
Console.WriteLine("WriteLine at the end of the try block.");
}
finally
{
// To run the program in Visual Studio, type CTRL+F5. Then
// click Cancel in the error dialog.
Console.WriteLine("\nExecution of the finally block after an unhandled\n" +
"error depends on how the exception unwind operation is triggered.");
Console.WriteLine("i = {0}", i);
}
}
// Output:
// Unhandled Exception: System.InvalidCastException: Specified cast is not valid.
//
// Execution of the finally block after an unhandled
// error depends on how the exception unwind operation is triggered.
// i = 123
}
but when I copied this to my .Net-Core console it doesn't execute finally and doesn't return the output in finally that I expect according to Microsoft says! it returns below and I don't know why!
I know that we can simply use try..catch block and resolve the problem. I just want to know this contradiction with Microsoft's sample and my experience!
And later on in the same paper they say
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.
in your case the exception is unhandled so finally is not guaranteed to be called
Check it here:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.
Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack. That is, you can catch the exception in the method that calls the method that contains the try-finally statement, or in the method that calls that method, or in any method in the call stack. If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.
When is this usually?
If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.
Exception unwind
When we enclose a block of code with a try statement compiler creates a step to store current context of the CPU in current stack frame with program counter pointed to start of catch block. If the CPU encounters any error it retrieves the context from stack an program counter jumps to catch statement.
Conditions when finally does not execute in a .net try..finally block
Some examples:
StackOverflowException
ExecutionEngineException
Application exit
Related
For a long time I thought that it allows me to free up all the resources in the finally block and I thought that if an exception happens in the try block, then the resources will still be free up in the finally block. But that seems not to be the case.
I have the following piece of code:
using System;
public sealed class Program
{
public static void Main()
{
try {
int zero = 0;
int i = 1/zero;
} finally {
Console.WriteLine("divide by zero"); //the line is never called
}
}
}
I never reach the line which prints to the console. That means that I will not be able to free up resource in finally block in this case on the exception being thrown inside the try block.
So, I believe there are two things: either I am missing something or the try + finally combination has no use cases in the C#. The second statement makes sense, because I will get the same functionality as is produced by the above code with the code below:
using System;
public sealed class Program
{
public static void Main()
{
int zero = 0;
int i = 1/zero;
Console.WriteLine("divide by zero"); //the line is never called
}
}
But I am afraid that I might be missing something here. So, could someone confirm that the combination is useless or prove that it is not, please?
UPDATE
After the comment which is able to call the finally block in its fiddle, I checked once more in the VS Code, and still I see no output.
You're assumptions are incorrect (sometimes) https://dotnetfiddle.net/hjqmOS
try-finally (C# Reference)
By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.
There are cases when it doesn't run though
Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered. That, in turn, is dependent on how your computer is set up.
Here is the important part
Usually, when an unhandled exception ends an application, whether or
not the finally block is run is not important. However, if you have
statements in a finally block that must be run even in that situation,
one solution is to add a catch block to the try-finally statement.
Alternatively, you can catch the exception that might be thrown in the
try block of a try-finally statement higher up the call stack.
try/catch/finally has nothing to do with freeing up resources. This is strictly application flow and error handling construct. You live in the managed code and garbage collector frees up resources. This construct does the following
try
{
int zero = 0;
int i = 1/zero;
}
catch (DividedByZeroException ex)
{
Console.WriteLine(Exception handled);
throw; // propagate ex to caller
}
finally
{
Console.WriteLine("Method ended execution"); // called with or without exception
}
I believe this is because you have VS to break on unhandled errors and thus VS steps in displaying the exception. If you compile it and run it manually on the command line I believe you will see "divide by zero". Also, instead of changing your VS settings, you can 'handle' the error and then should see the behavior you expect.
Example:
using System;
public sealed class Program
{
public static void Main()
{
try
{
int zero = 0;
int i = 1 / zero;
}
catch
{
}
finally
{
Console.WriteLine("divide by zero");
}
}
}
For a long time I thought that it allows me to free up all the resources in the finally block and I thought that if an exception happens in the try block, then the resources will still be free up in the finally block. But that seems not to be the case.
I have the following piece of code:
using System;
public sealed class Program
{
public static void Main()
{
try {
int zero = 0;
int i = 1/zero;
} finally {
Console.WriteLine("divide by zero"); //the line is never called
}
}
}
I never reach the line which prints to the console. That means that I will not be able to free up resource in finally block in this case on the exception being thrown inside the try block.
So, I believe there are two things: either I am missing something or the try + finally combination has no use cases in the C#. The second statement makes sense, because I will get the same functionality as is produced by the above code with the code below:
using System;
public sealed class Program
{
public static void Main()
{
int zero = 0;
int i = 1/zero;
Console.WriteLine("divide by zero"); //the line is never called
}
}
But I am afraid that I might be missing something here. So, could someone confirm that the combination is useless or prove that it is not, please?
UPDATE
After the comment which is able to call the finally block in its fiddle, I checked once more in the VS Code, and still I see no output.
You're assumptions are incorrect (sometimes) https://dotnetfiddle.net/hjqmOS
try-finally (C# Reference)
By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.
There are cases when it doesn't run though
Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered. That, in turn, is dependent on how your computer is set up.
Here is the important part
Usually, when an unhandled exception ends an application, whether or
not the finally block is run is not important. However, if you have
statements in a finally block that must be run even in that situation,
one solution is to add a catch block to the try-finally statement.
Alternatively, you can catch the exception that might be thrown in the
try block of a try-finally statement higher up the call stack.
try/catch/finally has nothing to do with freeing up resources. This is strictly application flow and error handling construct. You live in the managed code and garbage collector frees up resources. This construct does the following
try
{
int zero = 0;
int i = 1/zero;
}
catch (DividedByZeroException ex)
{
Console.WriteLine(Exception handled);
throw; // propagate ex to caller
}
finally
{
Console.WriteLine("Method ended execution"); // called with or without exception
}
I believe this is because you have VS to break on unhandled errors and thus VS steps in displaying the exception. If you compile it and run it manually on the command line I believe you will see "divide by zero". Also, instead of changing your VS settings, you can 'handle' the error and then should see the behavior you expect.
Example:
using System;
public sealed class Program
{
public static void Main()
{
try
{
int zero = 0;
int i = 1 / zero;
}
catch
{
}
finally
{
Console.WriteLine("divide by zero");
}
}
}
I have created the following C# program:
namespace dispose_test
{
class Program
{
static void Main(string[] args)
{
using (var disp = new MyDisposable())
{
throw new Exception("Boom");
}
}
}
public class MyDisposable : IDisposable
{
public void Dispose()
{
Console.WriteLine("Disposed");
}
}
}
When I run this using dotnet run, I see the following behavior:
Windows: Exception text written to console, "Disposed" printed ~20 second later, program exits.
Linux: Exception text written to console, program exits immediately. "Disposed" never written.
The delay on Windows is annoying, but the fact that Dispose() isn't called at all on Linux is troubling. Is this expected behavior?
EDITS Clarifications/additions from the conversation below:
This is not specific to using/Dispose(), which is just a special case of try/finally. The behavior also occurs generally with try/finally - the finally block is not run. I have updated the title to reflect this.
I have also checked for the execution of Dispose() by writing a file to the filesystem, just to ensure that problem wasn't related to stdout being disconnected from the console before Dispose() is run in the case of an unhandled exception. Behavior was the same.
Dispose() does get called if the exception is caught anywhere within the application. It's when it goes completely unhandled by the application that this behavior occurs.
On Windows, the long gap is not due to compilation delay. I started timing when the exception text was written to the console.
My original experiment was doing dotnet run on both platforms, which means separate compilations, but I have also tried by doing dotnet publish on Windows and directly running the output on both platforms, with the same result. The only difference is that, when run directly on Linux, the text "Aborted (core dumped)" is written after the exception text.
Version details:
dotnet --version -> 1.0.4.
Compiling to netcoreapp1.1, running on .NET Core 1.1.
lsb-release -d -> Ubuntu 16.04.1 LTS
Official response is that this is an expected behavior.
Interestingly enough, the C# doc page on try-finally explicitly calls this out right at the top (emphasis mine)
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up. For more information, see Unhandled Exception Processing in the CLR.
Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack. That is, you can catch the exception in the method that calls the method that contains the try-finally statement, or in the method that calls that method, or in any method in the call stack. If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.
One thing I found in my experimentation is that it doesn't appear to be enough to catch the exception, you have to handle it as well. If execution leaves the catch block via a throw, the finally will not run.
If you surround this with a try-catch, the finally block will run when the exception is caught (handled) by the outer catch.
static void Main(string[] args)
{
try
{
using (var disp = new MyDisposable())
{
throw new Exception("Boom");
}
}
catch (Exception e)
{
throw;
}
}
public virtual IQueryable<Hubs> getribbons(bool includeChildObjects)
{
using (var dbHelper = new DbHelper())
{
DbDataReaderExtended reader = null;
try
{
const string sqlQuery = "Select * From [ribbons]";
reader = dbHelper.ExecuteReader(sqlQuery, CommandType.Text, true);
IList<Hubs> models = new List<Hubs>();
while (reader.Read())
{
var model = GetHubDataFromReader(reader);
if (includeChildObjects)
{
model.Satellites = GetAllSatellites(true,model.HubID).ToList();
}
models.Add(model);
}
return models.AsQueryable();
}
finally
{
if (reader != null) { reader.Close(); }
}
}
}
Here this functon is in Business logic Layer. Here i need to handle exceptions in catch block and log it there and after throw it to the function it has called first(Presentation Layer). and then in finally i need to close all the things.
Please show me how to do error handling Here.
i am very new to C# please give me some clarifications on this this will be very helpful for me.
Thanks in advance
Finally blocks will be called whether or not there is a throw.
Using statements will call IDisposable.Dispose() on anything that isn't null once the scope of the Using block is exited.
By using a finally block, you can clean up any resources that are allocated in a try block, and you can run code even if an exception occurs in the try block. Typically, the statements of a finally block run when control leaves a try statement. The transfer of control can occur as a result of normal execution, of execution of a break, continue, goto, or return statement, or of propagation of an exception out of the try statement.
Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement. Alternatively, you can catch the exception that might be thrown in the try block of a try-finally statement higher up the call stack. That is, you can catch the exception in the method that calls the method that contains the try-finally statement, or in the method that calls that method, or in any method in the call stack. If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation.
using statement provides similar functionality(clear resources) only for IDisposable objects.
While in case of finally block, it will get executed regardless of whether or not there is an exception, provided that a catch block must be there in the call stack to catch the exception. Finally block can be used by developers to clear the resources on their own, that has not consumed IDispoable interface.
AFAIK, try and finally block are used execute a piece of code that might throw some exception, we also add catch block if we are prepared to handle some type of exception and/or are excepting them, like FileIOException, AccessRight or something. But when I ran this..
private void button1_Click(object sender, EventArgs e)
{
try
{
Environment.FailFast("It failed");
}
finally
{
MessageBox.Show("Done");
}
}
Its breaks with an exception and says
FatalExecutionEngineError was detected
Message: The runtime has encountered a fatal error. The address of the error was at 0x032526f4, on thread 0xd04. The error code is 0x80131623. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.
Now msdn says
Usually, when an unhandled exception ends an application, whether or
not the finally block is run is not important. However, if you have
statements in a finally block that must be run even in that situation,
one solution is to add a catch block to the try-finally statement.
So, I added the catch block, but still it says the same thing.
private void button1_Click(object sender, EventArgs e)
{
try
{
Environment.FailFast("It failed");
}
catch (Exception ex)
{
}
finally
{
MessageBox.Show("Done");
}
}
It failed again with the same error. As for CLR saying the code block in finally always runs (at least when catch is added), it surely is not the case. Reviews/Opinions anyone?
Also here's the snapshot..
This is by design. The purpose of Environment.FailFast is to halt execution immediately. By design it will not run any code in catch or finally blocks.
The documentation says:
This method terminates a process without running any active
try/finally blocks or finalizers.
The FailFast method writes the message string to the Windows
Application event log, creates a dump of your application, and then
terminates the current process. The messa string is also included in
error reporting to Microsoft.
Use the FailFast method instead of the Exit method to terminate your
application if the state of your application is damaged beyond repair,
and executing your application's try/finally blocks and finalizers
will corrupt program resources.
This makes it clear that code in your finally blocks will not run. If there was a way to make code run after Environment.FailFast then that would render Environment.FailFast pretty much useless. Its very existence is predicated on the fact that your code does not execute after you call it.
You point to documentation that states (emphasis mine):
Usually, when an unhandled exception ends an application, whether or not the finally block is run is not important. However, if you have statements in a finally block that must be run even in that situation, one solution is to add a catch block to the try-finally statement.
But those words simply do not apply here. You are assuming that when you call Environment.FailFast, an unhandled exception terminates the application. That is not the case. The application is just terminated on the spot – there is no unhandled exception.