簡潔なベンチマークはBlockingCollection<T>、実際には、 に指定されたタイムアウト値に関係なく、かなり迅速にハンドオーバーを実行することを示していますTryTake。
public async Task BlockingCollectionPerformance()
{
using (var collection = new BlockingCollection<int>())
{
var consumer = Task.Run(() =>
{
var i = 0;
while (collection.TryTake(out i, TimeSpan.FromSeconds(2)))
{
Debug.Print(i.ToString());
}
});
var producer = Task.Run(() =>
{
try
{
for (var i = 0; i < 10; i++)
{
collection.Add(i);
}
}
finally
{
collection.CompleteAdding();
}
});
await Task.WhenAll(producer, consumer);
}
}
上記は、私のボックスでは約 3 ミリ秒で完了します。
ただし、より具体的に言うとTryTake、項目がコレクションに追加されるたびに (そして をTryTake返すtrue)、またはブロッキング コレクションを呼び出しCompleteAddingたときに (この場合、タイムアウトを待っても意味がなく、 をTryTake返します)、すぐに戻りますfalse。呼び出しを行わない場合、必要以上に長くコンシューマーをブロックしたままにしておくことで、自分自身を撃つことができます。CompleteAddingTryTakefalse