title: Monodroid: Performing a full GC
body: <p>I try to create my small particle system. I have ParticleManager with list of Particles and draw my particles on canvas. I create any new objects like Paint and etc once just in init() function! If particle size is &lt; 0, I remove it:</p>
  
  <pre><code>for (int particle = 0; particle &lt; particles.Count; particle++)
      {
          particles[particle].Update(); //particle size--;
          if (!particles[particle].state) // size &gt; 0 ? true : false
          {
              particles[particle] = null; 
              //here I tried all variations like 
              //((IDisposable)particles[particle]).Dispose();
              //GC.SuppressFinalize(particles[particle]); 
              //System.GC.ReRegisterForFinalize(particles[particle]);
              //((Java.Lang.Object)particles[particle]).Dispose(); and etc             
  
              particles.Remove(particles[particle]);
          }
  </code></pre>
  
  <p>Then I create new Particle and add it to my list. What I see in my log:</p>
  
  <pre><code>GC cleanup summary: 1063 objects tested - resurrecting 1002.
  GC cleanup summary: 1053 objects tested - resurrecting 992.
  ...
  GC cleanup summary: 1052 objects tested - resurrecting 988.
  46800 outstanding GREFs. Performing a full GC!
  </code></pre>
  
  <p>And then I have 10-15(!!!) second pause in my render thread!!! I read official documentation, but it hasn't any solution. I analysed and compared my code with mono JetBoy example, but JetBoy's log hasn't anything about GC. Although I wrote my program with JetBoy's example. 
  How to fix full GC problem?</p>
  
  <hr>
  
  <p>Edit:
  MainThread.cs</p>
  
  <pre><code>public override void Run()
      {
          Log.Verbose("Run()", "r");
          Canvas c;
          while (mRun) {
              c = null;
              mPassedTime = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
              if (mTimerTask == null) {
                  mTimerTask = new CountDownTimerTask(this);
                  mTimer.Schedule(mTimerTask, mTaskIntervalInMillis);
              }
              try {
                  c = mSurfaceHolder.LockCanvas(null);
  
                  lock (mSurfaceHolder)
                      DoDrawRunning(c);
              } finally {
                  if (c != null)
                      mSurfaceHolder.UnlockCanvasAndPost(c);
              }
          }
      }
      private void DoDrawRunning(Canvas canvas)
      {
          #region particles
          for (int eng = 0; eng &lt; engines.Count; eng++)
          {   
              engines[eng].Update();
              engines[eng].Draw(canvas);
          }
          #endregion
      }
  </code></pre>
  
  <p>ParticleEnginee.cs</p>
  
  <pre><code>public void Update() {
          if (particles.Count &lt; maxTotal) {
              for (int i = 0; i &lt; total; i++) {
                  if (addNewB)
                      particles.Add(GenerateNewParticle()); // return new Particle
              }
          }
  
          for (int particle = 0; particle &lt; particles.Count; particle++) {
              particles[particle].Update(); // position and size update
              if (!particles[particle].state)  // size &gt; 0 ?
                  particles.RemoveAt(particle);
          }
      }
  public void Draw(Canvas canvas) {
          for (int j = 0; j &lt; 3; j++)  // 3 particle color-levels draw
              for (int index = 0; index &lt; particles.Count; index++) 
                  particles[index].Draw(canvas, j);
      }
  </code></pre>
  
  <p>Particle.cs</p>
  
  <pre><code>public void Draw(Canvas canvas) {
      mPaint.StrokeWidth = mSize;
      mPaint.Color = Color.Blue;
      canvas.DrawPoint(posX, posY, mPaint);
  }
  </code></pre>