Home All Groups Group Topic Archive Search About

FileStream.Close() Exception - How to release the lock?

Author
23 Mar 2007 11:53 AM
Fredrik Johansson
Hello!

Using .NET v2.0.50727, I've attached some sample code that creates a file in
a network path (test.er-1):
- The file is created at a network path.
- The user disconnects his/her network cable.
- The file is attempted to write to.
- The user reconnects his/her network cable.
- The file is closed - WHICH fails and results in the exception "The handle
is invalid"

This results in that the filelock remain active until the process is
terminated... Any suggestions on how to close the file in the same scenario?

Best Regards,
Fredrik Johansson


[code]
        private FileStream fs1;
        public void Runme() {
            lock (this) {
                string networkFile = @"\\anyserver\anyshare\test.er-";

                // open the file
                Console.Write("Creating Files (OK expected)...");
                try {
                    fs1 = new FileStream(networkFile + "1",
FileMode.CreateNew, FileAccess.Write, FileShare.Read);
                    Console.WriteLine("OK");
                } catch (Exception e) {
                    Console.WriteLine("FAILED\r\nThe test can not be
performed. Please modify the networkFile parameter!");
                    Console.WriteLine("\r\nPress ENTER to exit...");
                    Console.ReadLine();
                    return;
                }

                // wait for user to disconnect
                Console.Write("Please disconnect from your network, press
ENTER to continue...");
                Console.ReadLine();

                // try to write some data - this will fail
                try {
                    Console.Write("Attempting to Write (FAILED expected)...");
                    byte[] ba = Encoding.Default.GetBytes("Hello World");
                    fs1.Write(ba, 0, ba.Length);
                    fs1.Flush();
                    Console.WriteLine("OK - Did you really disconnect your
drive?");
                } catch (Exception e) {
                    Console.WriteLine("FAILED");
                }

                Console.Write("Please connect to your network, press ENTER
to continue...");
                Console.ReadLine();

                // try to close the file - this will fail
                try {
                    Console.Write("Closing File (this WILL fail)...");
                    fs1.Close();
                    fs1 = null;
                    Console.WriteLine("OK - Both files are supposidly
closed...");
                } catch (Exception e) {
                    //
===================================================================
                    // break here "The handle is invalid" - but the filelock
is still on?!
                    Console.WriteLine("FAILED");
                }

                Console.WriteLine("\r\nPress ENTER to exit...");
                Console.ReadLine();
            }
        }
[/code]

Author
23 Mar 2007 12:39 PM
Kevin Spencer
You have to close the file prior to disconnecting. You can re-open it
afterwards if you need to.

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
Networking Components, Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net

Show quote
"Fredrik Johansson" <FredrikJohans***@discussions.microsoft.com> wrote in
message news:5853CB7E-940B-4DA3-BBB4-A250672AECDC@microsoft.com...
> Hello!
>
> Using .NET v2.0.50727, I've attached some sample code that creates a file
> in
> a network path (test.er-1):
> - The file is created at a network path.
> - The user disconnects his/her network cable.
> - The file is attempted to write to.
> - The user reconnects his/her network cable.
> - The file is closed - WHICH fails and results in the exception "The
> handle
> is invalid"
>
> This results in that the filelock remain active until the process is
> terminated... Any suggestions on how to close the file in the same
> scenario?
>
> Best Regards,
> Fredrik Johansson
>
>
> [code]
>        private FileStream fs1;
>        public void Runme() {
>            lock (this) {
>                string networkFile = @"\\anyserver\anyshare\test.er-";
>
>                // open the file
>                Console.Write("Creating Files (OK expected)...");
>                try {
>                    fs1 = new FileStream(networkFile + "1",
> FileMode.CreateNew, FileAccess.Write, FileShare.Read);
>                    Console.WriteLine("OK");
>                } catch (Exception e) {
>                    Console.WriteLine("FAILED\r\nThe test can not be
> performed. Please modify the networkFile parameter!");
>                    Console.WriteLine("\r\nPress ENTER to exit...");
>                    Console.ReadLine();
>                    return;
>                }
>
>                // wait for user to disconnect
>                Console.Write("Please disconnect from your network, press
> ENTER to continue...");
>                Console.ReadLine();
>
>                // try to write some data - this will fail
>                try {
>                    Console.Write("Attempting to Write (FAILED
> expected)...");
>                    byte[] ba = Encoding.Default.GetBytes("Hello World");
>                    fs1.Write(ba, 0, ba.Length);
>                    fs1.Flush();
>                    Console.WriteLine("OK - Did you really disconnect your
> drive?");
>                } catch (Exception e) {
>                    Console.WriteLine("FAILED");
>                }
>
>                Console.Write("Please connect to your network, press ENTER
> to continue...");
>                Console.ReadLine();
>
>                // try to close the file - this will fail
>                try {
>                    Console.Write("Closing File (this WILL fail)...");
>                    fs1.Close();
>                    fs1 = null;
>                    Console.WriteLine("OK - Both files are supposidly
> closed...");
>                } catch (Exception e) {
>                    //
> ===================================================================
>                    // break here "The handle is invalid" - but the
> filelock
> is still on?!
>                    Console.WriteLine("FAILED");
>                }
>
>                Console.WriteLine("\r\nPress ENTER to exit...");
>                Console.ReadLine();
>            }
>        }
> [/code]
Author
23 Mar 2007 1:54 PM
Fredrik Johansson
And how do you find out when the user (or Windows) decides to disconnect the
network (or perhaps when the DHCP dies)?! We can't have buttons everywhere. I
think we need a more robust FileStream, if there isn't any workarounds.


Regards
Fredrik

Show quote
"Kevin Spencer" wrote:

> You have to close the file prior to disconnecting. You can re-open it
> afterwards if you need to.
>
> --
> HTH,
>
> Kevin Spencer
> Microsoft MVP
>
> Printing Components, Email Components,
> Networking Components, Controls, much more.
> DSI PrintManager, Miradyne Component Libraries:
> http://www.miradyne.net
>
> "Fredrik Johansson" <FredrikJohans***@discussions.microsoft.com> wrote in
> message news:5853CB7E-940B-4DA3-BBB4-A250672AECDC@microsoft.com...
> > Hello!
> >
> > Using .NET v2.0.50727, I've attached some sample code that creates a file
> > in
> > a network path (test.er-1):
> > - The file is created at a network path.
> > - The user disconnects his/her network cable.
> > - The file is attempted to write to.
> > - The user reconnects his/her network cable.
> > - The file is closed - WHICH fails and results in the exception "The
> > handle
> > is invalid"
> >
> > This results in that the filelock remain active until the process is
> > terminated... Any suggestions on how to close the file in the same
> > scenario?
> >
> > Best Regards,
> > Fredrik Johansson
> >
> >
> > [code]
> >        private FileStream fs1;
> >        public void Runme() {
> >            lock (this) {
> >                string networkFile = @"\\anyserver\anyshare\test.er-";
> >
> >                // open the file
> >                Console.Write("Creating Files (OK expected)...");
> >                try {
> >                    fs1 = new FileStream(networkFile + "1",
> > FileMode.CreateNew, FileAccess.Write, FileShare.Read);
> >                    Console.WriteLine("OK");
> >                } catch (Exception e) {
> >                    Console.WriteLine("FAILED\r\nThe test can not be
> > performed. Please modify the networkFile parameter!");
> >                    Console.WriteLine("\r\nPress ENTER to exit...");
> >                    Console.ReadLine();
> >                    return;
> >                }
> >
> >                // wait for user to disconnect
> >                Console.Write("Please disconnect from your network, press
> > ENTER to continue...");
> >                Console.ReadLine();
> >
> >                // try to write some data - this will fail
> >                try {
> >                    Console.Write("Attempting to Write (FAILED
> > expected)...");
> >                    byte[] ba = Encoding.Default.GetBytes("Hello World");
> >                    fs1.Write(ba, 0, ba.Length);
> >                    fs1.Flush();
> >                    Console.WriteLine("OK - Did you really disconnect your
> > drive?");
> >                } catch (Exception e) {
> >                    Console.WriteLine("FAILED");
> >                }
> >
> >                Console.Write("Please connect to your network, press ENTER
> > to continue...");
> >                Console.ReadLine();
> >
> >                // try to close the file - this will fail
> >                try {
> >                    Console.Write("Closing File (this WILL fail)...");
> >                    fs1.Close();
> >                    fs1 = null;
> >                    Console.WriteLine("OK - Both files are supposidly
> > closed...");
> >                } catch (Exception e) {
> >                    //
> > ===================================================================
> >                    // break here "The handle is invalid" - but the
> > filelock
> > is still on?!
> >                    Console.WriteLine("FAILED");
> >                }
> >
> >                Console.WriteLine("\r\nPress ENTER to exit...");
> >                Console.ReadLine();
> >            }
> >        }
> > [/code]
>
>
>
Author
23 Mar 2007 2:37 PM
Kevin Spencer
You always have those issues, in any application. Rule of thumb when using
File Streams. Open, write, close, as quickly as possible.

--
HTH,

Kevin Spencer
Microsoft MVP

Printing Components, Email Components,
Networking Components, Controls, much more.
DSI PrintManager, Miradyne Component Libraries:
http://www.miradyne.net

Show quote
"Fredrik Johansson" <FredrikJohans***@discussions.microsoft.com> wrote in
message news:D9FB7C42-221C-4DA2-BC4A-0C33FEE5DC18@microsoft.com...
> And how do you find out when the user (or Windows) decides to disconnect
> the
> network (or perhaps when the DHCP dies)?! We can't have buttons
> everywhere. I
> think we need a more robust FileStream, if there isn't any workarounds.
>
>
> Regards
> Fredrik
>
> "Kevin Spencer" wrote:
>
>> You have to close the file prior to disconnecting. You can re-open it
>> afterwards if you need to.
>>
>> --
>> HTH,
>>
>> Kevin Spencer
>> Microsoft MVP
>>
>> Printing Components, Email Components,
>> Networking Components, Controls, much more.
>> DSI PrintManager, Miradyne Component Libraries:
>> http://www.miradyne.net
>>
>> "Fredrik Johansson" <FredrikJohans***@discussions.microsoft.com> wrote in
>> message news:5853CB7E-940B-4DA3-BBB4-A250672AECDC@microsoft.com...
>> > Hello!
>> >
>> > Using .NET v2.0.50727, I've attached some sample code that creates a
>> > file
>> > in
>> > a network path (test.er-1):
>> > - The file is created at a network path.
>> > - The user disconnects his/her network cable.
>> > - The file is attempted to write to.
>> > - The user reconnects his/her network cable.
>> > - The file is closed - WHICH fails and results in the exception "The
>> > handle
>> > is invalid"
>> >
>> > This results in that the filelock remain active until the process is
>> > terminated... Any suggestions on how to close the file in the same
>> > scenario?
>> >
>> > Best Regards,
>> > Fredrik Johansson
>> >
>> >
>> > [code]
>> >        private FileStream fs1;
>> >        public void Runme() {
>> >            lock (this) {
>> >                string networkFile = @"\\anyserver\anyshare\test.er-";
>> >
>> >                // open the file
>> >                Console.Write("Creating Files (OK expected)...");
>> >                try {
>> >                    fs1 = new FileStream(networkFile + "1",
>> > FileMode.CreateNew, FileAccess.Write, FileShare.Read);
>> >                    Console.WriteLine("OK");
>> >                } catch (Exception e) {
>> >                    Console.WriteLine("FAILED\r\nThe test can not be
>> > performed. Please modify the networkFile parameter!");
>> >                    Console.WriteLine("\r\nPress ENTER to exit...");
>> >                    Console.ReadLine();
>> >                    return;
>> >                }
>> >
>> >                // wait for user to disconnect
>> >                Console.Write("Please disconnect from your network,
>> > press
>> > ENTER to continue...");
>> >                Console.ReadLine();
>> >
>> >                // try to write some data - this will fail
>> >                try {
>> >                    Console.Write("Attempting to Write (FAILED
>> > expected)...");
>> >                    byte[] ba = Encoding.Default.GetBytes("Hello
>> > World");
>> >                    fs1.Write(ba, 0, ba.Length);
>> >                    fs1.Flush();
>> >                    Console.WriteLine("OK - Did you really disconnect
>> > your
>> > drive?");
>> >                } catch (Exception e) {
>> >                    Console.WriteLine("FAILED");
>> >                }
>> >
>> >                Console.Write("Please connect to your network, press
>> > ENTER
>> > to continue...");
>> >                Console.ReadLine();
>> >
>> >                // try to close the file - this will fail
>> >                try {
>> >                    Console.Write("Closing File (this WILL fail)...");
>> >                    fs1.Close();
>> >                    fs1 = null;
>> >                    Console.WriteLine("OK - Both files are supposidly
>> > closed...");
>> >                } catch (Exception e) {
>> >                    //
>> > ===================================================================
>> >                    // break here "The handle is invalid" - but the
>> > filelock
>> > is still on?!
>> >                    Console.WriteLine("FAILED");
>> >                }
>> >
>> >                Console.WriteLine("\r\nPress ENTER to exit...");
>> >                Console.ReadLine();
>> >            }
>> >        }
>> > [/code]
>>
>>
>>
Author
23 Mar 2007 3:02 PM
Fredrik Johansson
But even then, that isn't any guarantee that this wouldn't happen. And
besides, that results in terrible performance when you do lots of writing
from any app... :)

After doing some research I decided to release the lock manually... The
trick is to get a copy of the Handle, after the file has been successfully
opened:
fs1 = new FileStream(...);
IntPtr handle = fs1.SafeFileHandle.DangerousGetHandle();

Then when the exception is thrown from the .Close(), all you have to do (to
release the lock) is:
try {
  fs1.Close();
} catch (Exception) {
  CloseHandle(handle);
}

CloseHandle is an external in kernel32, and imported by using the following
statement:
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success),
DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool CloseHandle(IntPtr handle);

Attribute namespaces are located in System.Runtime.InteropServices, and
System.Runtime.ConstrainedExecution.

Of course, one would think that FileStream (which by the way - is a great
class) could recover from this by itself, without any help from the coder.
It's not the 1900 anymore :)


Regards,
Fredrik

Show quote
"Kevin Spencer" wrote:

> You always have those issues, in any application. Rule of thumb when using
> File Streams. Open, write, close, as quickly as possible.
>
> --
> HTH,
>
> Kevin Spencer
> Microsoft MVP
>
> Printing Components, Email Components,
> Networking Components, Controls, much more.
> DSI PrintManager, Miradyne Component Libraries:
> http://www.miradyne.net
>
> "Fredrik Johansson" <FredrikJohans***@discussions.microsoft.com> wrote in
> message news:D9FB7C42-221C-4DA2-BC4A-0C33FEE5DC18@microsoft.com...
> > And how do you find out when the user (or Windows) decides to disconnect
> > the
> > network (or perhaps when the DHCP dies)?! We can't have buttons
> > everywhere. I
> > think we need a more robust FileStream, if there isn't any workarounds.
> >
> >
> > Regards
> > Fredrik
> >
> > "Kevin Spencer" wrote:
> >
> >> You have to close the file prior to disconnecting. You can re-open it
> >> afterwards if you need to.
> >>
> >> --
> >> HTH,
> >>
> >> Kevin Spencer
> >> Microsoft MVP
> >>
> >> Printing Components, Email Components,
> >> Networking Components, Controls, much more.
> >> DSI PrintManager, Miradyne Component Libraries:
> >> http://www.miradyne.net
> >>
> >> "Fredrik Johansson" <FredrikJohans***@discussions.microsoft.com> wrote in
> >> message news:5853CB7E-940B-4DA3-BBB4-A250672AECDC@microsoft.com...
> >> > Hello!
> >> >
> >> > Using .NET v2.0.50727, I've attached some sample code that creates a
> >> > file
> >> > in
> >> > a network path (test.er-1):
> >> > - The file is created at a network path.
> >> > - The user disconnects his/her network cable.
> >> > - The file is attempted to write to.
> >> > - The user reconnects his/her network cable.
> >> > - The file is closed - WHICH fails and results in the exception "The
> >> > handle
> >> > is invalid"
> >> >
> >> > This results in that the filelock remain active until the process is
> >> > terminated... Any suggestions on how to close the file in the same
> >> > scenario?
> >> >
> >> > Best Regards,
> >> > Fredrik Johansson
> >> >
> >> >
> >> > [code]
> >> >        private FileStream fs1;
> >> >        public void Runme() {
> >> >            lock (this) {
> >> >                string networkFile = @"\\anyserver\anyshare\test.er-";
> >> >
> >> >                // open the file
> >> >                Console.Write("Creating Files (OK expected)...");
> >> >                try {
> >> >                    fs1 = new FileStream(networkFile + "1",
> >> > FileMode.CreateNew, FileAccess.Write, FileShare.Read);
> >> >                    Console.WriteLine("OK");
> >> >                } catch (Exception e) {
> >> >                    Console.WriteLine("FAILED\r\nThe test can not be
> >> > performed. Please modify the networkFile parameter!");
> >> >                    Console.WriteLine("\r\nPress ENTER to exit...");
> >> >                    Console.ReadLine();
> >> >                    return;
> >> >                }
> >> >
> >> >                // wait for user to disconnect
> >> >                Console.Write("Please disconnect from your network,
> >> > press
> >> > ENTER to continue...");
> >> >                Console.ReadLine();
> >> >
> >> >                // try to write some data - this will fail
> >> >                try {
> >> >                    Console.Write("Attempting to Write (FAILED
> >> > expected)...");
> >> >                    byte[] ba = Encoding.Default.GetBytes("Hello
> >> > World");
> >> >                    fs1.Write(ba, 0, ba.Length);
> >> >                    fs1.Flush();
> >> >                    Console.WriteLine("OK - Did you really disconnect
> >> > your
> >> > drive?");
> >> >                } catch (Exception e) {
> >> >                    Console.WriteLine("FAILED");
> >> >                }
> >> >
> >> >                Console.Write("Please connect to your network, press
> >> > ENTER
> >> > to continue...");
> >> >                Console.ReadLine();
> >> >
> >> >                // try to close the file - this will fail
> >> >                try {
> >> >                    Console.Write("Closing File (this WILL fail)...");
> >> >                    fs1.Close();
> >> >                    fs1 = null;
> >> >                    Console.WriteLine("OK - Both files are supposidly
> >> > closed...");
> >> >                } catch (Exception e) {
> >> >                    //
> >> > ===================================================================
> >> >                    // break here "The handle is invalid" - but the
> >> > filelock
> >> > is still on?!
> >> >                    Console.WriteLine("FAILED");
> >> >                }
> >> >
> >> >                Console.WriteLine("\r\nPress ENTER to exit...");
> >> >                Console.ReadLine();
> >> >            }
> >> >        }
> >> > [/code]
> >>
> >>
> >>
>
>
>
Author
23 Mar 2007 4:31 PM
Fredrik Johansson
But even with this it doesn't seem like a good solution. I didn't think
~Finalizers or .Dispose should throw exceptions...

Does anyone got a suggestion? Perhaps the developers of SafeFileHandle has
something to say about this?

Best Regards,
Fredrik

AddThis Social Bookmark Button