A class destructor

T

Trecius

Hello, Newsgroupians:

Here's my situation. I have created a class that connects to another
device. It reads and sends information using a stream. The device it
connects to is proprietary and has its own set of commands. When I connect,
I can parse various properties of the system. However, when I am done, I
send it the "&EXIT." This tells the machine that I am disconnecting.

Now, I like ordered code just as much as the next person, so I try to create
my code with fault tolerances built into it. Therefore, if another
individual using my code forgets to call, Disconnect() which sends the
"&EXIT" message, I want to send that before the object is garbage collected.
This is synonymous to implementing a Dipose() method, and if the person
forgets to Dispose() the object, the destructor will do it for you.

However, I am running into problems. I purposefully forget to call
Disconnect(), so my destructor is calling my Disconnect() function. However,
my stream has already been marked and called for garbage collection. What
should I do?

An abbreviated example of my code is as follows...

~MyClass()
{
if (this.m_stream != null)
{
this.Disconnect();
}
}

public void Disconnect()
{
if (this.m_stream != null)
{
this.Write("&EXIT");
this.m_stream.Close();
this.m_stream = null;
}
}

Again, if someone hasn't called Disconnect(), the destructor should call
Disconnect(), but by that time the stream has already been called for garbage
collection. Maybe I should do GC.SuppressFinalize()? Thank you, all.


Trecius
 
D

Duggi

Hello, Newsgroupians:

Here's my situation.  I have created a class that connects to another
device.  It reads and sends information using a stream.  The device it
connects to is proprietary and has its own set of commands.  When I connect,
I can parse various properties of the system.  However, when I am done,I
send it the "&EXIT."  This tells the machine that I am disconnecting.

Now, I like ordered code just as much as the next person, so I try to create
my code with fault tolerances built into it.  Therefore, if another
individual using my code forgets to call, Disconnect() which sends the
"&EXIT" message, I want to send that before the object is garbage collected.  
This is synonymous to implementing a Dipose() method, and if the person
forgets to Dispose() the object, the destructor will do it for you.

However, I am running into problems.  I purposefully forget to call
Disconnect(), so my destructor is calling my Disconnect() function.  However,
my stream has already been marked and called for garbage collection.  What
should I do?

An abbreviated example of my code is as follows...

~MyClass()
{
  if (this.m_stream != null)
  {
    this.Disconnect();
  }

}

public void Disconnect()
{
  if (this.m_stream != null)
  {
    this.Write("&EXIT");
    this.m_stream.Close();
    this.m_stream = null;
  }

}

Again, if someone hasn't called Disconnect(), the destructor should call
Disconnect(), but by that time the stream has already been called for garbage
collection.  Maybe I should do GC.SuppressFinalize()?  Thank you, all..

Trecius

Can you try implementing Dispose() pattern? As I see you are facing
issue with non deterministic nature of GC.

-Cnu
 
P

Peter Morris

First I would implement IDisposable.

Next I would either

A: Create a stream class that writes &EXIT. It is the stream that owns the
unmanaged resource.
or
B: Throw an exception if you collect an instance that has not been closed.


FileStream for example will flush the contents if the handle is still
available, otherwise your file will just be missing some data. The idea is
that soon enough you will realise your data is missing and fix your bug.

I'd be more inclined to go for option B!
 
B

Ben Voigt [C++ MVP]

Trecius said:
Hello, Newsgroupians:

Here's my situation. I have created a class that connects to another
device. It reads and sends information using a stream. The device it
connects to is proprietary and has its own set of commands. When I
connect, I can parse various properties of the system. However, when
I am done, I send it the "&EXIT." This tells the machine that I am
disconnecting.

Now, I like ordered code just as much as the next person, so I try to
create my code with fault tolerances built into it. Therefore, if
another individual using my code forgets to call, Disconnect() which
sends the "&EXIT" message, I want to send that before the object is
garbage collected. This is synonymous to implementing a Dipose()
method, and if the person forgets to Dispose() the object, the
destructor will do it for you.

However, I am running into problems. I purposefully forget to call
Disconnect(), so my destructor is calling my Disconnect() function.
However, my stream has already been marked and called for garbage
collection. What should I do?

Ahh, well C# classes (and .NET types in general) haven't got destructors,
they have finalizers instead. And finalizers run when the object is no
longer reachable from the root(s). Your problem is that the Stream is only
referenced from your object, so when your object is unreachable the Stream
is also unreachable, and .NET gives no guarantees as to which finalizers run
first. However, there is a way to force your finalizer to run before the
Stream is finalized: make the Stream reachable.

for example, add as follows:


class MyClass
{
private static readonly Dictionary<object, Stream> ConnectedStreams =
new Dictionary<MyClass, Stream>();
private readonly object self = new object(); // now guaranteed unique
for each this, but won't keep MyClass instance alive like using this would

public Stream UnderlyingStream
{
get { return m_stream; }
private set { m_stream = value; ConnectedStreams[self] = value; }
}
~MyClass()
{
if (this.m_stream != null)
{
this.Disconnect();
}
}

public void Disconnect()
{
if (UnderlyingStream != null)
{
this.Write("&EXIT");
this.m_stream.Close();
this.m_stream.Dispose();
UnderlyingStream = null;
}
}
}
 
B

Ben Voigt [C++ MVP]

Trecius said:
Hello, Newsgroupians:

Here's my situation. I have created a class that connects to another
device. It reads and sends information using a stream. The device it
connects to is proprietary and has its own set of commands. When I
connect, I can parse various properties of the system. However, when
I am done, I send it the "&EXIT." This tells the machine that I am
disconnecting.

Now, I like ordered code just as much as the next person, so I try to
create my code with fault tolerances built into it. Therefore, if
another individual using my code forgets to call, Disconnect() which
sends the "&EXIT" message, I want to send that before the object is
garbage collected. This is synonymous to implementing a Dipose()
method, and if the person forgets to Dispose() the object, the
destructor will do it for you.

However, I am running into problems. I purposefully forget to call
Disconnect(), so my destructor is calling my Disconnect() function.
However, my stream has already been marked and called for garbage
collection. What should I do?

Note, in addition to my example using a static field, you could also use a
non-pinning GCHandle to keep the Stream alive.
 

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