In the library I created, I have a DataPort class that implements functionality similar to the .NET SerialPort class. He talks with some hardware and will raise an event when data arrives on this equipment. To implement this behavior, a DataPort creates a stream that is expected to have the same lifetime as the DataPort object. The problem is that when a DataPort goes out of scope, it never gets garbage collection
Now, since DataPort is negotiating with equipment (using pInvoke) and owning some unmanaged resources, it implements IDisposable. When you call Dispose on an object, everything happens correctly. DataPort gets rid of all unmanaged resources and kills the worker thread and leaves. However, if you simply miss the DataPort out of scope, the garbage collector will never call the finalizer, and the DataPort will remain in memory forever. I know this happens for two reasons:
- The finalizer breakpoint never hits
- SOS.dll tells me that DataPort is still alive
Sidebar: Before moving on, I will say yes, I know that the answer is "Dispose () Dummy!" but I think that even if you let all links go out of scope, the right thing should happen in the end, and the garbage collector should get rid of the DataPort
Back to the problem: Using SOS.dll, I see that the reason my DataPort is not collecting garbage is because the thread that it deployed still has a reference to the DataPort object - through the implicit "this" instance method parameter which is running the thread. The running workflow will not collect garbage , so any links that enter the workflow area cannot be selected for garbage collection either.
In the thread itself, the following code is executed mainly:
public void WorkerThreadMethod(object unused)
{
ManualResetEvent dataReady = pInvoke_SubcribeToEvent(this.nativeHardwareHandle);
for(;;)
{
int signalIndex = WaitHandle.WaitAny(new WaitHandle[] {this.dataReady, this.closeSignal});
if(signalIndex == 1)
{
return;
}
else
{
this.ProcessDataFromHardware();
dataReady.Reset()
}
}
}
Dispose () :
public void Dispose()
{
closeSignal.Set();
workerThread.Join();
}
gc DataPort, DataPort . , . , . ACK!
, , - 'this' WorkerThread ( . ). - ? , ! , ? msdn, .NET
:
- IsBackground true
- , , . , .