Disposing with related managed and unmanaged resources...

  • Thread starter Thread starter Volker Hetzer
  • Start date Start date
V

Volker Hetzer

Hi!
I've got a file container that, upon disposing, might try to write to a file.
Now, I want to tie the lifetime of that file to the lifetime of some object which also uses the container:

public class myFileObject
{
myFileObject()
{
_FileName=Path.GetTempFileName();
_FHC=new FileHandlingContainer(_FileName);
}
public void workWithFHC(Params)
{
_FHC.MethodInvocation(Params);
}
private FileHandlingContainer _FHC;
private string _FileName;
}

How would I now implement a Disposable Interface and a Finalizer?
The Problem I'm facing is that I need to guarantee that the file
gets deleted after _FHC is disposed. If not, then either I try to
delete an open file or _FHC tries to write to a deleted file.

The normal Dispose Pattern says that
- Dispose(true) should Dispose of _FHC and the file behind _FileName
- Dispose(false) only the file and
- ~myFileObject() should call Dispose(false)
But if the caller forgets using "using", the finalizer might delete the file
before _FHC has been disposed, right?

So, either "using" or the Garbage collector need to guarantee that _FHC
is dead before myFileObject deletes the file.

Does anyone have any idea? In C++ I'd use an auto_ptr<myFileObject> and do
the rest in the destructor but I have no idea how to do that in C#.

Lots of Greetings!
Volker
 
Volker said:
I've got a file container that, upon disposing, might try to write to a
file.
Now, I want to tie the lifetime of that file to the lifetime of some
object which also uses the container:

public class myFileObject
{
myFileObject()
{
_FileName=Path.GetTempFileName();
_FHC=new FileHandlingContainer(_FileName);
}
public void workWithFHC(Params)
{
_FHC.MethodInvocation(Params);
}
private FileHandlingContainer _FHC;
private string _FileName;
}

How would I now implement a Disposable Interface and a Finalizer?
The Problem I'm facing is that I need to guarantee that the file
gets deleted after _FHC is disposed. If not, then either I try to
delete an open file or _FHC tries to write to a deleted file.

The normal Dispose Pattern says that
- Dispose(true) should Dispose of _FHC and the file behind _FileName
- Dispose(false) only the file and
- ~myFileObject() should call Dispose(false)
But if the caller forgets using "using", the finalizer might delete the
file
before _FHC has been disposed, right?
In your current situation, the file doesn't exist as a managed object at all
(assuming FileHandlingContainer doesn't contain a FileStream instance), so
the finalizer will not do anything to it, nor do you have anything to say
about its lifetime. The file will be closed when FileHandlingContainer
(which presumably opens it) closes it or when the process terminates,
whichever comes first.

You could wrap the file in a FileStream and pass FileOptions.DeleteOnClose
to the constructor. That way, the file will be deleted when the last handle
to it closes, which will be either your FileStream-wrapped handle or the
handle contained by the FileHandlingContainer. This eliminates the need for
a finalizer as well.
 
Peter said:
[...]
How would I now implement a Disposable Interface and a Finalizer?
The Problem I'm facing is that I need to guarantee that the file
gets deleted after _FHC is disposed. If not, then either I try to
delete an open file or _FHC tries to write to a deleted file.

The normal Dispose Pattern says that
- Dispose(true) should Dispose of _FHC and the file behind _FileName
- Dispose(false) only the file and
- ~myFileObject() should call Dispose(false)
But if the caller forgets using "using", the finalizer might delete
the file
before _FHC has been disposed, right?

Right. Order of finalizers is not guaranteed.

I'm not wild about the design you've got here, but if you really want to
use it, it seems to me you simply need to dispose _FHC in the finalizer
as well.
I see. Since file deletion is expensive anyway, an additional round in the
GC wouldn't matter very much.

_FHC is a ZipPackage, by the way and Dispose() "flushes and saves the
contents..." and so on. I'd have no problems if Dispose were just busy with
cleanup and not worried about the state of the file. If someone wanted
to have a valid package he might just as well call Close().

The zip file gets used only until it is put into a database.
I want the user (caller) not to worry about the temporary file, so
I tie the lifetime of the file to the lifetime of my ZipPackage/Zipfile
object.
That way, the user might or might not use Dispose but, barring crashes,
the temporary file will be deleted.
The "Dispose pattern" you reference is just a general
guideline, and can't possibly address all possible scenarios.
You mean, I have to think??! Oh, bother...
But thanks for the encouragement. :-)
Fortunately, Jeroen solves the special case here quite nicely.

Lots of Greetings and Thanks!
Volker
 
Jeroen said:
You could wrap the file in a FileStream and pass
FileOptions.DeleteOnClose to the constructor. That way, the file will be
deleted when the last handle to it closes, which will be either your
FileStream-wrapped handle or the handle contained by the
FileHandlingContainer. This eliminates the need for a finalizer as well.
Sounds great!
Thanks a lot!
Volker
 
Back
Top