1

I am writing an ASCOM telescope driver and I need to guarantee that a few serial port commands are sent to the scope to stop the scope from moving when an client application fails to disconnect properly or crashes.

I tried adding a finalizer that looks something like this

~Telescope()
{
    Common.AbortSlew();
    Common.SetTracking(false);
}

it makes it to the SendSerialPortCommand() method and then quits without actually sending the bytes out on the wire and seems to quit just before a lock statement.

repo can be viewed here

http://code.google.com/p/ascom-nexstar-telescope/source/browse/NexStar/

finalizer is in driver.cs called methods are in static class Common

is there a better or more reliable way to accomplish this?

PeskyGnat
  • 2,454
  • 19
  • 22
user964078
  • 33
  • 2

4 Answers4

4

Implement IDisposable interface and do your work in Dispose method.

You should see this article from Greg Beech: Implementing and using the IDisposable interface

Instead of destructors, .NET has finalizers which are implemented by overriding the Finalize method defined on the base Object class (though C# somewhat confusingly uses the C++ destructor syntax ~Object for this). If an object overrides the Finalize method then rather than being collected by the GC when it is out of scope, the GC places it on a finalizer queue. In the next GC cycle all finalizers on the queue are run (on a single thread in the current implementation) and the memory from the finalized objects reclaimed. It's fairly obvious from this why you don't want to do clean up in a finalizer: it takes two GC cycles to collect the object instead of one and there is a single thread where all finalizers are run while every other thread is suspended, so it's going to hurt performance.

So if you don't have destructors, and you don't want to leave the cleanup to the finalizer, then the only option is to manually, deterministically, clean up the object. Enter the IDisposable interface which provides a standard for supporting this functionality and defines a single method, Dispose, where you put in the cleanup logic for the object. When used within a finally block, this interface provides equivalent functionality to destructors. The reason for finally blocks in code is primarily to support the IDisposable interface; this is why C++ uses simply try/except as there is no need for a finally block with destructors.

Habib
  • 219,104
  • 29
  • 407
  • 436
  • Thanks that did help me understand the problem a little more, the root cause of this issue is that the application using the driver is unmanaged C++ and the driver is managed C# so only ~Telescope() will only ever get called and I don't have the authority to enforce that the unmanaged C++ application properly disconnect from the driver by setting the Connected property to false. – user964078 Aug 10 '12 at 21:17
1

You can write a service that monitors you application and when it exits or crashes restarts.

Jacob Seleznev
  • 8,013
  • 3
  • 24
  • 34
0

Implementing IDisposable is a very good idea for your API.
I would also consider to write a proxy service which is between your driver and the ASCON.
Unsafe Stops via the Task Manager can still lead to bad stops.

weismat
  • 7,195
  • 3
  • 43
  • 58
0

OK, the problem was that my managed C# ASCOM driver is being used by an unmanaged C++ application that would not disconnect from the driver properly by setting the Connected property to false then exiting, so I was trying to use a C# finalizer to catch this case and stop the scope which did not work probably referencing managed object's in the shutdown code.

the workaround was using the appdomain.currentdomain.processexit event to run my shutdown code before the finalizer/destructor runs.

user964078
  • 33
  • 2