排队嵌套线程

Queueing Nested Threads

在我的程序中,产品(或成分)需要更新自己的 parents 价格,那些 parents 必须为他们的 parents 做同样的事情等等。

我写过这样的方法:

public static Price CalculatePrice(this IProduct pro)
{
    /// calculation stuff
}

private static SystemContext innerContext;

/// <summary>
/// In the main controller this method called for updates
/// </summary>
/// <param name="pro"></param>
/// <param name="sc"></param>
public static void UpdatePrice(this IProduct pro, ref SystemContext sc)
{
    if (sc.Relations.Where(t => t.SubProduct.ID == pro.ID).Any())
    {

        // If this returns any, this means there are some products using this product as their sub-product.
        var list = sc.Relations.Where(t => t.SubProduct.ID == pro.ID).ToList();

            ConcurrentQueue<Relation> quee = new ConcurrentQueue<Relation>(list);

            innerContext = new SystemContext();

            Task task = new Task(() => UpdatePrice(ref quee));
            task.Start();
    }
}


private static void UpdatePrice(ref ConcurrentQueue<Relation> queue)
{
    Relation val;

    while (queue.TryDequeue(out val))
    {
        val.Product.Price = val.Product.CalculatePrice();

        var list = innerContext.Relations.Where(t => t.SubProduct.ID == val.Product.ID);

        if (list.Any())
        {
            ConcurrentQueue<Relation> quee = new ConcurrentQueue<Relation>(list);
            Task task = new Task(() => UpdatePrice(ref quee));
            task.Start();

        }
    }
}

尽管 parent 产品的第一级得到更新,但第二级没有。

这样做有更好的逻辑吗?

顺便说一句,任何最低级别的产品都有大约 1000 parents(递归)。这意味着耗时(因为价格的计算)。所以如果你在提建议的时候也考虑到时间就完美了...

编辑

当我在做一些测试的时候。我想,一些最低级别的产品有 4000 parents.

我认为解决方案可能是迭代地而不是递归地处理数据。您可以通过将您感兴趣的所有产品添加到列表中并在处理其中的产品时不断添加到该列表中来实现。

像这样:

public static void UpdatePrice(this IProduct pro, ref SystemContext sc)
{
    var relations = sc.Relations.Where(t => t.SubProduct.ID == pro.ID).ToList();

    for (int i = 0; i < relations.Count; i++)
    {
        relations[i].Product.Price = relations[i].Product.CalculatePrice();
        relations.AddRange(sc.Relations.Where(t => t.SubProduct.ID == relations[i].Product.ID)); 
    }    
}