Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is C#'s using statement abort-safe?

I've just finished reading "C# 4.0 in a Nutshell" (O'Reilly) and I think it's a great book for a programmer willing to switch to C#, but it left me wondering. My problem is the definition of using statement. According to the book (p. 138),

using (StreamReader reader = File.OpenText("file.txt")) {     ... } 

is precisely equivalent to:

StreamReader reader = File.OpenText("file.txt"); try {     ... } finally {     if (reader != null)         ((IDisposable)reader).Dispose(); } 

Suppose, however, that this is true and that this code is executed in a separate thread. This thread is now aborted with thread.Abort(), so a ThreadAbortException is thrown and suppose the thread is exactly after initializing the reader and before entering the try..finally clause. This would mean that the reader is not disposed!

A possible solution would be to code this way:

StreamReader reader = null; try {     reader = File.OpenText("file.txt");     ... } finally {     if (reader != null)         ((IDisposable)reader).Dispose(); } 

This would be abort-safe.

Now for my questions:

  1. Are authors of the book right and the using statement is not abort-safe or are they wrong and it behaves like in my second solution?
  2. If using is equivalent to the first variant (not abort-safe), why does it check for null in finally?
  3. According to the book (p. 856), ThreadAbortException can be thrown anywhere in managed code. But maybe there are exceptions and the first variant is abort-safe after all?

EDIT: I know that using thread.Abort() is not considered good practice. My interest is purely theoretical: how does the using statement behave exactly?

like image 207
DzinX Avatar asked Oct 13 '10 12:10

DzinX


People also ask

What is this C language?

C is an imperative procedural language supporting structured programming, lexical variable scope, and recursion, with a static type system. It was designed to be compiled to provide low-level access to memory and language constructs that map efficiently to machine instructions, all with minimal runtime support.

Is C -- a coding language?

C-- (pronounced C minus minus) is a C-like programming language. Its creators, functional programming researchers Simon Peyton Jones and Norman Ramsey, designed it to be generated mainly by compilers for very high-level languages rather than written by human programmers.

Is C same as C+?

While both C and C++ may sound similar, their features and usage are different. C is a procedural programming language and does not support objects and classes. C++ is an enhanced version of C programming with object-oriented programming support.


2 Answers

The book's companion web site has more info on aborting threads here.

In short, the first translation is correct (you can tell by looking at the IL).

The answer to your second question is that there may be scenarios where the variable can be legitimately null. For instance, GetFoo() may return null here, in which you wouldn't want a NullReferenceException thrown in the implicit finally block:

using (var x = GetFoo()) {    ... } 

To answer your third question, the only way to make Abort safe (if you're calling Framework code) is to tear down the AppDomain afterward. This is actually a practical solution in many cases (it's exactly what LINQPad does whenever you cancel a running query).

like image 74
Joe Albahari Avatar answered Sep 22 '22 23:09

Joe Albahari


There's really no difference between your two scenarios -- in the second, the ThreadAbort could still happen after the call to OpenText, but before the result is assigned to the reader.

Basically, all bets are off when you get a ThreadAbortException. That's why you should never purposely abort threads rather than using some other method of gracefully bringing the thread to a close.

In response to your edit -- I would point out again that your two scenarios are actually identical. The 'reader' variable will be null unless the File.OpenText call successfully completes and returns a value, so there's no difference between writing the code out the first way vs. the second.

like image 24
Clyde Avatar answered Sep 22 '22 23:09

Clyde