1

Что такое идиоматический и быстрый способ сделать следующее на C#? Скажем, у меня есть класс, который имеет три значения (всегда три значения так предварительно выделить 3 задачи в порядке):Вычислить несколько значений параллельно. Подождите, пока все потоки закончатся.

public class AggregateValues 
{ 
    public double A { get; set;} 
    public double B { get; set;} 
    public double C { get; set;} 
} 

public AggregateValues Compute() 
{ 
    //How do I parallize these? 
    AggregateValues av = new AggregateValues(); 
    av.A = ComputeA(); 
    av.B = ComputeB(); 
    av.C = ComputeC(); 

    //Wait for ComputeA, ComputeB, ComputeC to be done 

    return av; 
} 

public double ComputeA() 
{ 
    // Complicated code 
} 

public double ComputeB() 
{ 
    // Complicated code 
} 

public double ComputeC() 
{ 
    // Complicated code 
} 
+1

Если вы можете использовать asyncs, методы WaitAll/WhenAll будут самым чистым способом сделать это. http://stackoverflow.com/questions/25009437/running-multiple-async-tasks-and-waiting-for-them-all-to-complete –

ответ

3

Вы можете использовать метод Task.WaitAll ждать для всех задач, чтобы закончить. Ниже приведено простое решение для вашего случая.

public AggregateValues Compute() 
{ 
    //How do I parallize these? 
    AggregateValues av = new AggregateValues(); 

    Task taskA = Task.Factory.StartNew(() => av.A = ComputeA()); 
    Task taskB = Task.Factory.StartNew(() => av.B = ComputeB()); 
    Task taskC = Task.Factory.StartNew(() => av.C = ComputeC()); 

    //Wait for ComputeA, ComputeB, ComputeC to be done 
    Task.WaitAll(taskA, taskB, taskC); 

    return av; 
} 

ждут на Task.WhenAll может также использоваться, чтобы ждать все задачи, которые будут завершены.

+0

Спасибо, что работает. Мне интересно, насколько эффективна «Task taskA = Task.Factory.StartNew (() => av.A =« Я думаю, я всегда могу статически распределять их. – Ivan

2

Если ComputeA, ComputeB и ComputeC не асинхронные (и они не находятся в вашем коде, потому что они возвращаются double вместо Task<double>), то вы можете использовать Parallel.Invoke:

public AggregateValues Compute() 
{ 
    AggregateValues av = new AggregateValues(); 
    Parallel.Invoke(
     () => { av.A = ComputeA(); }, 
     () => { av.B = ComputeB(); }, 
     () => { av.C = ComputeC(); }); 
    return av; 
} 

В вашем сценарии, Parallel.Invoke немного лучше, чем Task.WaitAll или Task.WhenAll, потому что Parallel.Invoke может повторно использовать вызывающий поток для одной из задач.

+0

Я собираюсь посмотреть, какая из них быстрее. – Ivan

Смежные вопросы