一つの解決策は、優れたThreading in C# E-bookからです。基本的な構造に関するセクションでは、著者はあなたが探しているものをほぼ正確に作成しますin an example。
このリンクをクリックして、プロデューサ/コンシューマキューにスクロールします。
以降のセクションでは、ConcurrentQueueも正常に機能すると指摘していますが、並行性の高いシナリオを除いてすべて悪化します。しかし、あなたの低負荷のケースでは、簡単に何かを手に入れるほうが良いかもしれません。私は文書からの主張に個人的な経験はありませんが、あなたが評価するためにそこにあります。
こちらがお役に立てば幸いです。
Edit2:Evkの提案(ありがとう!)に応じて、BlockingCollectionクラスはあなたの望むように見えます。デフォルトでは、フードの下でConcurrentQueueを使用します。私は特にCompleteAddingメソッドが好きで、それとCancellationTokensを使うことができます。状況が「ブロッキング」しているときに「シャットダウン」シナリオが正しく説明されているとは限りませんが、これは正しいIMOです。
編集3:要求に応じて、これがBlockingCollectionでどのように機能するかのサンプル。 )(私はスリープに追加
using System.Collections.Concurrent;
private static void testMethod()
{
BlockingCollection<Action> myActionQueue = new BlockingCollection<Action>();
var consumer = Task.Run(() =>
{
foreach(var item in myActionQueue.GetConsumingEnumerable())
{
item(); // Run the task
}// Exits when the BlockingCollection is marked for no more actions
});
// Add some tasks
for(int i = 0; i < 10; ++i)
{
int captured = i; // Imporant to copy this value or else
myActionQueue.Add(() =>
{
Console.WriteLine("Action number " + captured + " executing.");
Thread.Sleep(100); // Busy work
Console.WriteLine("Completed.");
});
Console.WriteLine("Added job number " + i);
Thread.Sleep(50);
}
myActionQueue.CompleteAdding();
Console.WriteLine("Completed adding tasks. Waiting for consumer completion");
consumer.Wait(); // Waits for consumer to finish
Console.WriteLine("All actions completed.");
}
他のものが消費されている間、あなたは物事が追加されていることを見ることができるように呼び出します:私は、問題の消費者側のために、これは、よりコンパクトにするforeach
とGetConsumingEnumerable
を使用しました。また、任意の数のconsumer
ラムダを起動することもできます(Action
と呼び、Action
を複数回起動します)。いつでも、コレクション上でCount
に電話して、実行されていないタスクの数を取得することができます。おそらくゼロでない場合、プロデューサのタスクが実行されていると考えられます。
ConcurrentQueueと一緒にBlockingCollectionを見ると、多くの例があります。 BlockingCollectionから消費されるスレッドを開始し、メインループからそのスレッドへのアイテムを開始します。 – Evk
タスクとカスタムTaskSchedulerは、デリゲートを順番に実行する場合はおそらくトリックを行います。カスタムTaskSchedulerを構築する方法については、http://www.infoworld.com/article/3063560/application-development/building-your-own-task-scheduler-in-c.htmlを参照してください。あなたの代理人が並行して実行されても構わないのであれば、標準の.NET TaskSchedulerはおそらく大丈夫です。 –
すべてを1つのスレッドに保持し、async-awaitを使用して非同期ワークフローを構築することを検討してください。 **非同期は並行性**ではないことを覚えておいてください。 2つのCookを雇うことなく、同時に卵とトーストを調理できるように、非同期ワークフローを1つのスレッドですべて実行できます。 –