2015-01-04 2 views
2

В моей программе продукт (или ингредиент) должен обновить свои собственные цены родителей, и эти родители должны сделать то же самое для своих родителей и так далее.Queuing Nested Threads

Я написал метод, как это:

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(); 

     } 
    } 
} 

Хотя, первый уровень родительских продуктов обновляются, второй уровень не является.

Есть ли лучшая логика для этого?

И, кстати, любой из продуктов самого низкого уровня имеет приблизительно 1000 родителей (рекурсивно). Это означает, что требуется много времени (из-за расчета цены). Так что было бы идеально, если вы обратите внимание на время и когда вы даете совет ...

Редактировать

В то время как я делал некоторые испытания. Я полагал, что некоторые продукты с низким уровнем дохода имеют 4000 родителей.

+0

Рассматривали ли вы с помощью рекурсии? Кроме того, зачем вам нужен поток для каждого родителя? –

+0

Да. Я получил исключение StackOverflow без многопоточности. – paroxit

+1

О, теперь я вижу, что у вас 1000 родителей. Доступны ли эти родители только для рекурсивного прохождения каждого объекта? См. [This] (http://stackoverflow.com/questions/141467/recursive-list-flattening) для примера. –

ответ

2

Я думаю, что решение может состоять в том, чтобы обрабатывать данные итеративно, а не рекурсивно. Вы можете сделать это, добавив все интересующие вас товары в список и продолжайте добавлять их в этот список при обработке продуктов в нем.

Что-то вроде этого:

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)); 
    }  
} 
+0

Но в рамках вашего предложения нет части, которая обновляет цену второго или любого родителя выше уровня. – paroxit

+0

они будут обработаны в последующих итерациях цикла, просто добавьте их в список в теле цикла –

+0

Как я могу добавить родителей в этот список без рекурсии? Это не кажется возможным. – paroxit