1

我有一个场景,我想调用函数但希望有条件地调用它们。所以在下面的代码中,只会调用函数 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
);
4

3 回答 3

1

如果我学得正确,您只想执行列表中存在的一些操作。为什么不直接用 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),然后以并行方式执行他们的操作。很清楚,我猜。

如果要返回一些值,请分别使用FuncandSelect而不是Actionand ForAll

于 2017-04-24T22:58:32.063 回答
1

如果您需要执行结果,Parallel并且Action无法为您获取函数结果,但如果我们使用Task并且Func<T>我们可以在并行运行它们后获取结果。

我在下面的示例中添加了使用Task而不是Parallel让函数同时运行并允许您存储结果。我假设int函数 1、2 和 3 的返回类型 - 您可以更改它以满足您的需要。

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(...)Parallel.ForEach(...)但我认为这会引入一些不必要的开销。

于 2017-04-22T00:56:51.957 回答
0

我现在正在处理一些并行任务,并且我正在使用 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);
        }

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

如果您想尝试一下, 这里还有一个解决方案的.net fiddle。

于 2020-02-05T06:47:21.820 回答