By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
460,028 Members | 1,108 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 460,028 IT Pros & Developers. It's quick & easy.

In case FileStream fails, the GC throws an exception in another thread that cannot be caught

P: n/a

Hi!
In the example below, once the media is full, the FileSteam.WriteByte throws
an exception and the code
is designed to handle it. However, when the GC is invoked, it calls the
Finalize of FileSteam, who is trying
to flush and close the stream, but the disk is full, so the flush fails and
another exception is thrown from another
(GC) thread. An ugly solution would be to use GC.SuppressFinalize(fs).
Is there a better solution or good practice? (closing withot flushing
perhaps)?

many thanks,
M. Rapp

--------------------------------

Example:

static void Main(string[] args)
{
try
{
FileStream fs =
new FileStream(args[0], FileMode.Create);
Console.WriteLine("starting to write...");
while (true)
fs.WriteByte(0xff);
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}",
e.Message);
}
Console.WriteLine("press any key to continue");
Console.Read();
}
Nov 15 '05 #1
Share this Question
Share on Google+
3 Replies


P: n/a
Have you tried wrapping the use of your FileStreamer in a "using" block?
Something like:

using(FileStream fs =
new FileStream(args[0], FileMode.Create)) {
Console.WriteLine("starting to write...");
while (true)
fs.WriteByte(0xff);
}

You can always wrap the using block inside your try/catch block, but using
the implicit Dispose pattern you should be able to force the finalization to
occur in your thread (if I am not wrong).

using(
"Muki Rapp" <ra**@notalvision.com> wrote in message
news:uI**************@TK2MSFTNGP11.phx.gbl...

Hi!
In the example below, once the media is full, the FileSteam.WriteByte throws an exception and the code
is designed to handle it. However, when the GC is invoked, it calls the
Finalize of FileSteam, who is trying
to flush and close the stream, but the disk is full, so the flush fails and another exception is thrown from another
(GC) thread. An ugly solution would be to use GC.SuppressFinalize(fs).
Is there a better solution or good practice? (closing withot flushing
perhaps)?

many thanks,
M. Rapp

--------------------------------

Example:

static void Main(string[] args)
{
try
{
FileStream fs =
new FileStream(args[0], FileMode.Create);
Console.WriteLine("starting to write...");
while (true)
fs.WriteByte(0xff);
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}",
e.Message);
}
Console.WriteLine("press any key to continue");
Console.Read();
}

Nov 15 '05 #2

P: n/a
Hi!
I am afraid this is not the solution to the problem.
'using' will force the dispose method to be called and
exception to be thrown in the same thread, but still
at the end of the process the GC will also try to dispose
the filestream and an exception will be thrown in a DIFFERENT thread (run
example below for demonstration,
when filename path is a small floppy disk)

Any other ideas?

try
{
using(FileStream fs =
new FileStream(args[0], FileMode.Create))
{

while (true)
fs.WriteByte(0xff);

}
}
catch (Exception e)
{
Console.WriteLine("Exception: " + e.Message);
}

"Stefano "WildHeart" Lanzavecchia" <st********@apl.it> wrote in message
news:u4*************@tk2msftngp13.phx.gbl...
Have you tried wrapping the use of your FileStreamer in a "using" block?
Something like:

using(FileStream fs =
new FileStream(args[0], FileMode.Create)) {
Console.WriteLine("starting to write...");
while (true)
fs.WriteByte(0xff);
}

You can always wrap the using block inside your try/catch block, but using
the implicit Dispose pattern you should be able to force the finalization to occur in your thread (if I am not wrong).

using(
"Muki Rapp" <ra**@notalvision.com> wrote in message
news:uI**************@TK2MSFTNGP11.phx.gbl...

Hi!
In the example below, once the media is full, the FileSteam.WriteByte

throws
an exception and the code
is designed to handle it. However, when the GC is invoked, it calls the
Finalize of FileSteam, who is trying
to flush and close the stream, but the disk is full, so the flush fails

and
another exception is thrown from another
(GC) thread. An ugly solution would be to use GC.SuppressFinalize(fs).
Is there a better solution or good practice? (closing withot flushing
perhaps)?

many thanks,
M. Rapp

--------------------------------

Example:

static void Main(string[] args)
{
try
{
FileStream fs =
new FileStream(args[0], FileMode.Create);
Console.WriteLine("starting to write...");
while (true)
fs.WriteByte(0xff);
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}",
e.Message);
}
Console.WriteLine("press any key to continue");
Console.Read();
}


Nov 15 '05 #3

P: n/a
> > > An ugly solution would be to use GC.SuppressFinalize(fs).
Is there a better solution or good practice? (closing withot flushing perhaps)?


I think you will have to use GC.SuppressFinalize(fs) after trying a
call to Dispose() or close() or using statement.
The FileStream's dispose (and IMO most "good" dispose methods) call
GC.SuppressFinalize at the end of the method call. However, because
of the exception, it is not getting called. So I wouldn't feel too
bad about manually supressing finalization.

I can't think of any other way to prevent an exception from being
raised on the Finalizer thread or catching that exception once thrown.

// a sample dispose function
void Dispose()
{
Dispose(true); // exception firing within this event...
GC.SuppressFinalize(this);
}

Although I do wonder if the file will continue to be locked since
Dispose was never called successfully. In the below program, it does
look like the file will be locked. Argh!

public static void Main ()
{
FileStream fs = new FileStream(@"A:\new.txt",
FileMode.Create);
bool diskfull = false;
try
{
while (true)
fs.WriteByte(0xff);
}
catch (IOException e)
{
Console.WriteLine("Exception: " + e.Message);
diskfull = true; // technically should only be set for
IOException when disk really is full.
}
finally
{
if (diskfull)
{
GC.SuppressFinalize(fs);
}
else
{
fs.Close();
}
}

// let's check to see if the file is locked.
try
{
using (FileStream fs1 = new FileStream(@"A:\new.txt",
FileMode.Open))
{
fs.ReadByte();
}
}
catch (Exception ex)
{
Console.WriteLine ("Exception: " + ex.Message);
}

Console.ReadLine();
}

Nov 15 '05 #4

This discussion thread is closed

Replies have been disabled for this discussion.