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

G

Guest

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();
}
}
 
K

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
 
G

Guest

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 said:
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 said:
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();
}
}
 
K

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

Fredrik Johansson said:
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 said:
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 said:
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();
}
}
 
G

Guest

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

Kevin Spencer said:
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 said:
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 said:
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

message 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();
}
}
 
G

Guest

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top