具有并发调度程序的异步生产者 - 消费者应用程序

时间:2014-10-06 12:24:24

标签: c# .net semaphore tpl-dataflow

我正在使用BufferBlock实现Producer-Consumer。代码运行良好。

static async Task Produce(ITargetBlock<int> queue)
{
    try
    {
        // Post messages to the block asynchronously. 
        for (int i = 0; i < 100; i++)
        {
            Console.WriteLine("Sending: {0}", i);
            await queue.SendAsync(i);
        }
    }
    finally 
    {
        queue.Complete();
    }
}

static async Task Consume(ISourceBlock<int> queue)
{
    // Read messages from the block asynchronously. 
    while (await queue.OutputAvailableAsync())
    {
        int value = await queue.ReceiveAsync();
        Console.WriteLine("Receiving: {0}", value);
    }
}

static void Main(string[] args)
{
    // Create a BufferBlock<int> object. 
    var queue = new BufferBlock<int>();

    try
    {
        var produce = Produce(queue);
        var consume = Consume(queue);

        Task.WaitAll(produce, consume, queue.Completion);
    }
    catch (Exception exception)
    {
        Console.WriteLine("An exception was thrown: {0}", exception.Message);
        Console.WriteLine("Terminating...");
    }
}

现在我有一个限制问题,我希望消费者的最大并发数是4.我想使用SemaphoreSlim机器人不知道如何应用它。

注意:这是一个并发调度问题,而不是并行问题。

1 个答案:

答案 0 :(得分:3)

如果您想要的是一次只能消耗一定数量的金额,您可以多次拨打TryRecieve,直到它为空,或达到金额。这是一个处理它的扩展方法:

public static bool TryReceive<T>(this BufferBlock<T> bufferBlock, int count, out IList<T> items)
{
    items = new List<T>();   
    for (var i = 0; i < count; i++)
    {
        T item;
        if (bufferBlock.TryReceive(out item))
        {
            items.Add(item);
        }
        else
        {
            break;
        }
    }
    return items.Any();
}

所以消费者变成了:

static async Task Consume(BufferBlock<int> queue)
{
    // Read messages from the block asynchronously. 
    while (await queue.OutputAvailableAsync())
    {
        IList<int> values;
        queue.TryReceive(4, out values);
        Console.WriteLine("Receiving: {0}", string.Join(", ", values));
    }
}