管理多线程流程

时间:2012-03-19 09:13:27

标签: c# multithreading

我得到了一项任务,我发现它非常具有挑战性,我不知道如何开始。

以下是问题:

我有一个随机产品队列(由A,B和C类型组成),

P [A],P [A],P [B],P [C],P [C],P [A],P [B],P [B] ....

我会同时将这些产品发送到ProcessProduct(),但不能同时处理两种相同类型的产品。

以下是该方案:

第一个P [A]得到处理,第二个P [A]必须等待第一个,第三个P [B]和第四个P [C]将立即得到处理,第五个P [C]将不得不等待前一个....

希望我的描述不会太混乱。 如果有人能给我一些建议,我将不胜感激。 谢谢。

4 个答案:

答案 0 :(得分:1)

执行此操作的一种方法是将项目分为三个不同的队列,每个类型一个队列。这会增加一些开销,但会让它变得更容易。

这是一些伪代码:

queueForTypeA=new queue()
queueForTypeB=new queue()
queueForTypeC=new queue()

foreach product in products
    if product is typeof A
        addLastInQueue(queueForTypeA, product)
    if product is typeof B
        addLastInQueue(queueForTypeB, product)
    if product is typeof C
        addLastInQueue(queueForTypeC, product)

然后你可以单独处理每个队列,而不必担心你一次处理2个相同类型的队列。

但是,此解决方案无法很好地扩展,如果您添加其他类型的产品,则需要更改代码,这不是最佳选择。

所以另一种选择是拥有一个您正在处理的类型列表,然后每次要处理新产品时,如果产品类型在{{1}中,您将重新访问队列中的第一个项目} -list,你跳过排队并接下一个。

答案 1 :(得分:1)

按类型对产品清单进行分组,然后并行处理每个组。

<强> EDITED

这是示例(如果产品列表是静态的):

sealed class Product
{
    public string Type
    {
        get;
        set;
    }
}

sealed class ProductProcessor
{
    public void StartProcessing(IEnumerable<Product> products)
    {
        foreach (var group in products.GroupBy(x => x.Type))
            Task.Factory.StartNew(() => ProcessProducts(group));
    }

    private void ProcessProducts(IEnumerable<Product> products)
    {
        foreach (Product product in products)
            ProcessProduct(product);
    }

    private void ProcessProduct(Product product)
    {

    }
}

这是产品的动态队列的另一个例子(我没有运行代码,将其作为一种伪代码读取):

sealed class ProductProcessor
{
    public void Process(Product product)
    {
        lock (_queues)
        {
            if (_queues.ContainsKey(product.Type))
                _queues[product.Type].Enqueue(product);
            else
            {
                ConcurrentQueue<Product> queue = new ConcurrentQueue<Product>();
                queue.Enqueue(product);

                _queues.Add(product.Type, queue);

                WaitCallback action = delegate(object state)
                {
                    Product productToProcess;
                    while (queue.TryDequeue(out productToProcess))
                    {
                        ProcessProduct(productToProcess);
                    }

                    lock (_queues) _queues.Remove(product.Type);
                };

                ThreadPool.QueueUserWorkItem(action);
            }
        }
    }

    private Dictionary<string, ConcurrentQueue<Product>> _queues
        = new Dictionary<string, ConcurrentQueue<Product>>();

    private void ProcessProduct(Product product)
    {

    }
}

P.S。您可以使用ConcurrentDictionary而不是锁。

答案 2 :(得分:0)

使用按产品类型索引的生产者 - 消费者队列数组。仅从每个队列挂起一个线程,因此为每个产品类型顺序调用ProcessProduct()。

答案 3 :(得分:0)

只需为每种类型使用一个队列。然后每个队列一次只能有一个作业。  所以你可以在队列中使用线程。

我甚至不能在这里看到问题?你在问什么?代码示例?功能 ?

因为你似乎被困在概念上,但大部分似乎都在这里。 关键是只影响每个队列的一个线程(如果你不需要直接使用线程,那么就是工作)