internal void Add(IntPtr handle) { if (handle == IntPtr.Zero) { return; } bool performCollect = false; int currentCount = 0; lock (this) { handleCount++; #if DEBUG_HANDLECOLLECTOR Debug.Assert(!handles.Contains(handle)); handles.Add(handle); #endif performCollect = NeedCollection(); currentCount = handleCount; } lock (internalSyncObject) { if (HandleCollector.HandleAdded != null) { HandleCollector.HandleAdded(name, handle, currentCount); } } if (!performCollect) { return; } if (performCollect) { #if DEBUG_HANDLECOLLECTOR Debug.WriteLine("HC> Forcing garbage collect"); Debug.WriteLine("HC> name :" + name); Debug.WriteLine("HC> threshHold :" + (threshHold).ToString()); Debug.WriteLine("HC> handleCount :" + (handleCount).ToString()); Debug.WriteLine("HC> deltaPercent:" + (deltaPercent).ToString()); #endif GC.Collect(); // We just performed a GC. If the main thread is in a tight // loop there is a this will cause us to increase handles forever and prevent handle collector // from doing its job. Yield the thread here. This won't totally cause // a finalization pass but it will effectively elevate the priority // of the finalizer thread just for an instant. But how long should // we sleep? We base it on how expensive the handles are because the // more expensive the handle, the more critical that it be reclaimed. int sleep = (100 - deltaPercent) / 4; System.Threading.Thread.Sleep(sleep); } }