Stream preventing owner garbage collection

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(;;)
  {
    //Wait here until we have data, or we got a signal to terminate the thread because we're being disposed
    int signalIndex = WaitHandle.WaitAny(new WaitHandle[] {this.dataReady, this.closeSignal});
    if(signalIndex == 1) //closeSignal is at index 1
    {
      //We got the close signal.  We're being disposed!
      return; //This will stop the thread
    }
    else
    {
      //Must've been the dataReady signal from the hardware and not the close signal.
      this.ProcessDataFromHardware();
      dataReady.Reset()
    }
  }
}

Dispose () :

public void Dispose()
{
  closeSignal.Set();
  workerThread.Join();
}

gc DataPort, DataPort . , . , . ACK!

, , - 'this' WorkerThread ( . ). - ? , ! , ? msdn, .NET

:

  • IsBackground true
  • , , . , .
+5
2

"This", "This" :

public static void WorkerThreadMethod(object thisParameter)
{
  //Extract the things we need from the parameter passed in (the DataPort)
  //dataReady used to be 'this.dataReady' and closeSignal used to be
  //'this.closeSignal'
  ManualResetEvent dataReady = ((DataPort)thisParameter).dataReady;
  WaitHandle closeSignal = ((DataPort)thisParameter).closeSignal;

  thisParameter = null; //Forget the reference to the DataPort

  for(;;)
  {
    //Same as before, but without "this" . . .
  }
}

, !

SOS.dll, , DataPort, ThreadHelper. , , Thread.Start(this);, ThreadHelper , , , "" ( ). . - DataPort. :

//Code that starts the thread:
  Thread.Start(new WeakReference(this))
//. . .
public static void WorkerThreadMethod(object weakThisReference)
{
  DataPort strongThisReference= (DataPort)((WeakReference)weakThisReference).Target;

  //Extract the things we need from the parameter passed in (the DataPort)
  ManualResetEvent dataReady = strongThisReferencedataReady;
  WaitHandle closeSignal = strongThisReference.closeSignal;

  strongThisReference= null; //Forget the reference to the DataPort.

  for(;;)
  {
    //Same as before, but without "this" . . .
  }
}

. ThreadHelper WeakReference, . , DataPort , DataPort. , , , DataPort. , DataPort, . GC , Dispose, . .

, (, , )! , , ? , ?

: , , WaitHandle.WaitAny(), - , , Threadpool . , DLL , , DLL.

+4

, , , , . "using", . http://msdn.microsoft.com/en-us/library/yh598w02.aspx, . , , , ( , ) .

0

All Articles