PC Review


Reply
Thread Tools Rate Thread

A class destructor

 
 
Trecius
Guest
Posts: n/a
 
      20th Oct 2008
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

 
Reply With Quote
 
 
 
 
Duggi
Guest
Posts: n/a
 
      20th Oct 2008
On Oct 20, 7:42*pm, Trecius <Trec...@discussions.microsoft.com> wrote:
> 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
 
Reply With Quote
 
Peter Morris
Guest
Posts: n/a
 
      20th Oct 2008
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!




--
Pete
====
http://mrpmorris.blogspot.com
http://www.capableobjects.com

 
Reply With Quote
 
Ben Voigt [C++ MVP]
Guest
Posts: n/a
 
      20th Oct 2008
Trecius wrote:
> 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;
}
}
}


>
> 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



 
Reply With Quote
 
Ben Voigt [C++ MVP]
Guest
Posts: n/a
 
      20th Oct 2008
Trecius wrote:
> 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.

>
>
> Trecius



 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Closing database connections in a class destructor Mark Rae Microsoft C# .NET 15 28th Apr 2005 09:53 AM
Destructor for VB.NET class Mika M Microsoft VB .NET 2 4th Apr 2005 01:03 PM
C++ vc C#. Destructor of not created class get called. Daniel O'Connell [C# MVP] Microsoft Dot NET Framework 5 5th Jun 2004 04:57 PM
C++ vc C#. Destructor of not created class get called. Daniel O'Connell [C# MVP] Microsoft C# .NET 5 5th Jun 2004 04:57 PM
ICE on VC7.1 when destructor is defined but not delcared in class Jonathan Turkanis Microsoft VC .NET 3 5th Apr 2004 08:16 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 12:17 AM.