有条件地并行调用

时间:2017-04-21 23:56:09

标签: c# task parallel.foreach parallel.invoke

我有一个场景,我想调用函数但希望它们有条件地调用。因此,在下面的代码中,只会调用函数2和3。但是,Action部分不返回值,但在我的情况下,我想存储返回值。

List<int> list = new List<int> {2,3};
Dictionary<int, Action> actions = new Dictionary<int, Action>()
{
   {1, Function1},
   {2, Function2},
   {3, Function3}
};

Parallel.Invoke((from action in list select actions[action]).ToArray());

最初我所拥有的是代码,但这将调用所有函数。有什么想法吗?

Parallel.Invoke(
 () => return1=function1,
 () => return2=function2,
 () => return3=function3
);

3 个答案:

答案 0 :(得分:0)

如果您需要执行结果,ParallelAction无法获得功能结果,但是如果我们使用Task和{{1}我们可以在并行运行结果后得到结果。

我在下面的示例中添加了使用Func<T>而不是Task来让函数同时运行并允许您存储结果。我假设Parallel为函数1,2和3的返回类型 - 您可以根据需要对其进行更改。

int

最后请注意,您可以将List<int> list = new List<int> { 2, 3 }; Dictionary<int, Func<int>> actions = new Dictionary<int, Func<int>>() { {1, Function1}, {2, Function2}, {3, Function3} }; List<Task<int>> taskList = (from a in list select Task.Run(actions[a])).ToList(); // Allow all processing to finish before accessing results Task.WaitAll(taskList.ToArray()); int result = taskList[0].Result; taskList.ForEach(...)交换,但我认为这会带来一些不必要的开销。

答案 1 :(得分:0)

如果我正确学习了,你只想执行列表中存在的一些操作。为什么不把它写在C#?

var hs = new HashSet<int> { 2, 3 };
var actions = new Dictionary<int, Action>()
{
   {1, Function1},
   {2, Function2},
   {3, Function3}
};

actions.Where(x => hs.Contains(x.Key)).AsParallel().ForAll(x => x.Value());

他们如何读取它:使用所需键集(在本例中为2和3)中显示的所有键对,然后以并行方式执行它们的操作。很清楚,我猜。

如果您想要返回一些值,请分别使用FuncSelect代替ActionForAll

答案 2 :(得分:0)

我现在正在处理一些并行任务,并且我正在使用Parallel.Invoke,最终我切换了将动作称为列表的方式,并在其上调用了Parallel.ForEach。最终为我节省了1.2 ms /每行。太棒了所以我想我会以为我在问你在问什么。

        int Function1(int input)
        {
            return 10 * input;
        }
        int Function2(int input)
        {
            return 20 * input;
        }
        int Function3(int input)
        {
            return 30 * input;
        }
        List<int> list = new List<int> { 2, 3 };
        Dictionary<int, Func<int, int>> actions = new Dictionary<int, Func<int, int>>()
        {
           {1, (arg) => Function1(arg)},
           {2, (arg) => Function2(arg)},
           {3, (arg) => Function3(arg)}
        };
        var bag = new ConcurrentBag<int>();

        Parallel.ForEach(actions,  action => { 
            if(action.Key == 2 || action.Key == 3)
            {
                bag.Add(action.Value.Invoke(3));
            }                
        });

        foreach(var number in bag)
        {
            Console.WriteLine(number);
        }

我认为您想要做的是有条件地调用方法,然后存储这些Funcs的收益。我有点困惑,因为您使用的是Action(不返回任何内容)。所以我将它们切换到Func,这是Function接受一个int,然后返回和int。我还添加了一些内联函数,以使代码能够从复制和粘贴中运行。

如果您想稍微尝试一下,这里还有一个solution的.net小提琴。