C# 決まった数だけThreadを動かし続ける (タイマー発火)

##Cancel操作(CancellationTokenSourceなど)省いてあります

#テストの為のTextBoxとButton

```
private System.Windows.Forms.TextBox log;
private System.Windows.Forms.Button button1;
```

#管理側

```csharp:[Test.cs]
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Test {
  public partial class Test : Form {
    private System.Threading.Timer timer = null;
    Object lockobj = new Object ();

    public Test () {
      InitializeComponent ();
    }

    public void LogOut (String s) {
      try {
        if (!String.IsNullOrEmpty (s)) {
          Invoke ((MethodInvoker) (() => {
            lock (lockobj) {
              log.AppendText (s + System.Environment.NewLine);
              log.SelectionStart = log.TextLength;
              log.ScrollToCaret ();
            }
          }));
        }
      } catch (Exception) {;}
    }

    static private int TimerPeriod = 10000;
    static private UInt64 taskmax = 2;
    private List<OneTask> tasks = new List<OneTask> ();
    private ReaderWriterLock tasklistlock = new ReaderWriterLock ();

    private UInt64 ExcuteTaskCount () {
      UInt64 result = 0;
      foreach (OneTask t in tasks)
        if (t.status == OneTask.Status.run)
          result++;
      return result;
    }

    public void ArroundTheWatchTower (Object arg) {
      timer.Change (Timeout.Infinite, Timeout.Infinite);
      List<OneTask> removeTask = new List<OneTask> ();
      try {
        tasklistlock.AcquireWriterLock (300000);
        foreach (OneTask t in tasks) {
          switch (t.status) {
            case OneTask.Status.wait:
              if (ExecuteTaskCount () < taskmax) {
                Task.Run (() => {
                  t.execute ();
                });
                System.Threading.Thread.Sleep (1000);
              }
              break;
            case OneTask.Status.finish:
              removeTask.Add (t);
              break;
          }
        }
        foreach (OneTask t in removeTask)
          tasks.Remove (t);
      }
      finally {
        tasklistlock.ReleaseWriterLock ();
      }
      timer.Change (0, TimerPeriod);
    }

    private void Test_Load (Object sender, EventArgs e) {
      if (timer == null)
        timer = 
          new System.Threading.Timer (ArroundTheWatchTower, null, 0, TimerPeriod);
      else
        timer.Change (0, TimerPeriod);
    }

    private void button1_Click (Object sender, EventArgs e) {
      try {
        tasklistlock.AcquireWriterLock (300000);
        for (UInt32 i = 0; i < 20; i++)
          tasks.Add (OneTask.OneTaskCreate (this));
      } finally {
        tasklistlock.ReleaseWriterLock ();
      }
    }
  }
}
```

#本体

```csharp:[OneTask.cs]
using System;

namespace Test {
  class OneTask {
    public enum Status {wait, run, finish};
    static private UInt64 nowkey = 0;

    protected Test parent = null;
    public UInt64 key {private set; get;}
    public Status status {protected set; get;}

    static public OneTask OneTaskCreate (Test test) {return new OneTask (test);}
    protected OneTask (Test test) {
      parent = test;
      key = nowkey++;
      status = Status.wait;
    }

    public void execute () {
      status = Status.run;
      parent.LogOut (ToString ());
      System.Threading.Thread.Sleep (10000);
      status = Status.finish;
      parent.LogOut (ToString ());
    }

    public override String ToString () {
      return @"OneTask Key=" + key.ToString () + @" Status=" + status;
    }
  }
}
```