C# 带条件的并行调用

C# 带条件的并行调用,c#,task,parallel.foreach,parallel.invoke,C#,Task,Parallel.foreach,Parallel.invoke,我有一个场景,我想调用函数,但希望它们被有条件地调用。因此,在下面的代码中,只调用函数2和3。但是,动作部分不返回值,但在我的例子中,我希望存储返回值 List<int> list = new List<int> {2,3}; Dictionary<int, Action> actions = new Dictionary<int, Action>() { {1, Function1}, {2, Function2}, {3, F

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

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
Action
将无法获得函数结果,但是如果我们使用
Task
Func
可以在并行运行后获得结果

我在下面的示例中添加了使用
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;
List List=新列表{2,3};
字典操作=新建字典()
{
{1,函数1},
{2,函数2},
{3,函数3}
};
List taskList=(从列表中选择Task.Run(actions[a])).ToList();
//允许在访问结果之前完成所有处理
Task.WaitAll(taskList.ToArray());
int result=taskList[0]。结果;

最后请注意,您可以将
taskList.ForEach(…)
Parallel.ForEach(…)
进行交换,但我认为这将引入一些不必要的开销。

如果我学习正确,您只需要执行列表中的一些操作。为什么不直接写在C#上呢

var hs=newhashset{2,3};
var actions=newdictionary()
{
{1,函数1},
{2,函数2},
{3,函数3}
};
actions.Where(x=>hs.Contains(x.Key)).AsParallel().ForAll(x=>x.Value());
他们的阅读方式:获取一组所需密钥(本例中为2和3)中包含密钥的所有对,然后以并行方式执行它们的操作。我想很清楚


如果要返回一些值,请分别使用
Func
Select
,而不是
Action
ForAll

我现在正在处理一些并行任务,我使用的是parallel.Invoke。最后,我切换了调用列表中的操作的方式,并调用了parallel.ForEach。结果我每排剃掉1.2毫秒。太棒了。所以我想我会试试你的要求

        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);
        }
int函数1(int输入)
{
返回10*输入;
}
int函数2(int输入)
{
返回20*输入;
}
int函数3(int输入)
{
返回30*输入;
}
列表=新列表{2,3};
字典操作=新建字典()
{
{1,(arg)=>Function1(arg)},
{2,(arg)=>Function2(arg)},
{3,(arg)=>Function3(arg)}
};
var bag=新的ConcurrentBag();
Parallel.ForEach(actions,action=>{
if(action.Key==2 | | action.Key==3)
{
bag.Add(action.Value.Invoke(3));
}                
});
foreach(袋中的var编号)
{
控制台写入线(编号);
}
我认为您试图做的是有条件地调用这些方法,然后存储这些函数的返回。我有点困惑,因为您使用的是Action(不返回任何内容)。所以我把它们切换到Func,它是一个取int,返回和int的函数。我还添加了一些内联函数,这样代码就可以通过复制和粘贴运行


若你们想玩一玩的话,这里还有一个.net的提琴

对于未调用的函数,应该返回什么?为什么要使用构造函数创建
任务
,然后调用
开始
,而不是只使用
任务。运行
?很好,我在使用
并行。ForEach
,但没有正确切换回
任务
。最好的解决方案是使用
Task.Run
而不是
Task.Start
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());
        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);
        }