IEnumerable を使用して協調マイクロスレッディングをシミュレートできます。残念ながら、これはブロッキング API では機能しないため、ポーリングできる API、またはシグナリングに使用できるコールバックを持つ API を見つける必要があります。
方法を検討する
IEnumerable Thread ()
{
//do some stuff
Foo ();
//co-operatively yield
yield null;
//do some more stuff
Bar ();
//sleep 2 seconds
yield new TimeSpan (2000);
}
C# コンパイラはこれをステート マシンにアンラップしますが、外観は共同マイクロスレッドのようになります。
パターンは非常に簡単です。すべてのアクティブな IEnumerator のリストを保持する「スケジューラ」を実装します。リストを循環しながら、MoveNext () を使用してそれぞれを「実行」します。MoveNext の値が false の場合、スレッドは終了しており、スケジューラはそのスレッドをリストから削除します。true の場合、スケジューラは Current プロパティにアクセスして、スレッドの現在の状態を判断します。それが TimeSpan の場合、スレッドはスリープを希望し、スケジューラはスレッドを何らかのキューに移動しました。このキューは、スリープ タイムスパンが終了したときにメイン リストにフラッシュバックできます。
他のリターン オブジェクトを使用して、他のシグナリング メカニズムを実装できます。たとえば、ある種の WaitHandle を定義します。スレッドがこれらのいずれかを生成すると、ハンドルが通知されるまで待機キューに移動できます。または、待機ハンドルの配列を生成することで、WaitAll をサポートできます。優先順位を実装することもできます。
私は約 150LOC でこのスケジューラーの簡単な実装を行いましたが、まだコードをブログに書いていません。これは PhyreSharp PhyreEngine ラッパー (非公開) 用であり、デモの 1 つで数百の文字を制御するのに非常にうまく機能しているようです。Unity3D エンジンから概念を借用しました。Unity3D エンジンには、ユーザーの観点から説明するオンライン ドキュメントがいくつかあります。