views:

87

answers:

3

Hi,

got a issue: I create singleton helper object that wraps PerformanceCounter objects. It implements IDisposable... But now I have spotted that when I close my test sample console host application, counters are still visible in perfmon tool (in production I will be hosted in Windows Service) , and are still running.

I figured out that Dispose is called inside finalizer, but then I don't dispose managed resources - which are PerformanceCounter objects. What should I do to make sure that resources are appropriately freed?

Thanks, Pawel

+1  A: 

Check the code below to see if you're using the disposable pattern. The finalizer should call your dispose method explicitly.

class DisposableObject : IDisposable
{
    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected void Dispose(bool disposing)
    {
        if (disposing)
        {
            // dispose managed resources
        }
        // dispose unmanaged resources
    }

    ~DisposableObject()
    {
        this.Dispose(false);
    }
}
Steven
Yeap . I follow that pattern, true dispose code is under// dispose managed resources comment. So when app crushes finalizer is called and disposing is set to false.
dragonfly
@dragonfly - The finalizer isn't guaranteed to be called if your application crashes. See the Remarks section of the object.Finalize method: http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx
tvanfosson
even better :) thx.
dragonfly
+2  A: 

If your application crashes, there's not much you can do to make sure that the unmanaged resources are disposed. You should properly implement the disposable pattern, with your unmanaged resources being disposed (if they haven't been already) when the object is finalized. In this way, you will release your resources when the service is shutdown but in the event of a hard crash your code probably won't be running anyway.

I'd suggest, especially if you're hosting in a Windows service which might automatically restart your code, that you write your code with the expectation that it might crash, leaving the unmanaged resources around and reuse/reclaim them if possible. Short of that, you should also be very defensive in your programming to make sure that any crashes are rare (and beyond your control).

tvanfosson
+1  A: 

This is normal behavior for performance counters. They are global "objects" that exist even if no process is generating data for them. You can, for example, select one of the .NET perf counters even if not a single .NET program is running on the machine. If the counter is actively generating data even if you don't have a process running anymore that updates its value then you may have selected an inappropriate CounterType.

Review the InstanceLifetime property to see if the Process value is appropriate for your counter.

Hans Passant
That is what I've been looking for. My counters are strictly instance-related, and should be discarded when process exits. What is mode I use MultiInstance approach.Thanks!
dragonfly
Ehh, I was happy to early :) InstanceLifetime of counter is Global. But I can't get to know, how to change it to Process :/Any ideas?
dragonfly
Exception:The InstanceLifetime cannot be set after the instance has been initialized. You must use the default constructor and set the CategoryName, InstanceName, CounterName, InstanceLifetime and ReadOnly properties manually before setting the RawValue.
dragonfly
ehh, got it (use default ctor!): performanceCounter = new PerformanceCounter(); performanceCounter.InstanceLifetime = PerformanceCounterInstanceLifetime.Process; performanceCounter.CategoryName = categoryInfo.Name; performanceCounter.CounterName = enumerator.Current.Value.Name; performanceCounter.InstanceName = this._instanceName; performanceCounter.ReadOnly = false;
dragonfly