首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >并行执行带有参数的方法

并行执行带有参数的方法
EN

Stack Overflow用户
提问于 2021-06-10 16:37:36
回答 1查看 338关注 0票数 0

我对异步和并行编程很陌生,我的问题围绕着尝试运行一个带有几个参数的方法,然后并行地执行该方法。我需要并行运行它,因为正在调用的方法是更新我工厂层上的PLC。如果它是向下同步,这个过程可能需要近10分钟,因为有多少。我可以让方法运行一次,在我的自定义类中使用最后一个PLC,但不会运行列表中的其他PLC。示例代码如下:

代码语言:javascript
复制
List<Task> task = new List<Task>();
foreach(PLC plc in PlcCollection)
{
    string plcName = plc.Name;
    string tagFormat = plc.TagFormat
    tasks.Add(Task.Run(async () => await MakeTags(plcName, tagFormat)));
}

Parallel.ForEach(tasks, task => task.Start());

// Code to be done after tasks are complete

public async Task MakeTags(string plcName, string tagFormat)
{
    //Code to update the PLC's
}

方法makeTags的工作方式,它应该被调用-它更新正确的可编程控制器。但是它只运行了一次,而且只运行了我的一个PLC值。对于同样的问题,我也尝试过Task.WhenAll(tasks)而不是Parallel.ForEach。有人对我做错了什么以及我可以尝试的任何事情有任何建议和反馈吗?谢谢!

编辑:为了澄清-我期待MakeTags方法将并行执行,但在PlcCollection中有许多PLC(数字将是可变的)。我得到的是,MakeTags方法只被调用一次,对于一个PLC元素,当集合中有多个PLC时。这个过程是从一个web应用程序开始的,然后服务器来处理剩下的部分。没有更新或更改UI元素。都是幕后工作。

编辑2:见下面的屏幕截图的调试器。在本例中,2个PLC (TTC_WALL和RR_HEPA_EE)被加载到我的任务列表中。但是,只有RR_HEPA_EE被处理,然后程序就完成了,而没有抛出异常。

编辑3:我做了修改,现在代码如下所示:

代码语言:javascript
复制
List<Task> task = new List<Task>();
foreach(PLC plc in PlcCollection)
{
    //plcName and tagFormat are just strings
    tasks.Add(MakeTags(plcName, tagFormat);
}

Task.WhenAll(tasks).ContinueWith(t =>
{
    //Code to do
    Console.WriteLine("****PLC Update Complete*****");
});

return; //program ends

public async Task MakeTags(string plcName, string tagFormat)
{
await Task.Run(() =>
{
    Console.WriteLine("Updating PLC " + plcName);
    //Code to update the PLC's
Console.WriteLine("PLC Updated for :" + plcName);
});
return;
}

然而,我仍然只有一个任务要运行。调试器屏幕截图下面,显示只有一个的2个PLC的更新。我应该看到控制台上写着“可编程控制器更新为TTC_WALL”。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-06-10 19:21:32

问题可能是您的代码没有等待任务的完成。您可以通过使用阻塞的Task.WaitAll方法等待它们全部完成。

代码语言:javascript
复制
Task[] tasks = PlcCollection
    .Select(plc => MakeTagsAsync(plc.Name, plc.TagFormat))
    .ToArray();
Task.WaitAll(tasks);
Console.WriteLine("****PLC Update Complete*****");

这样,当前线程将被阻塞,直到所有任务都完成为止,并且任何可能发生的异常都将出现在AggregateException中。

以上方法假设MakeTagsAsync方法是真正异步的。如果不是,而是通过在Task.Run内部包装一些同步代码来伪造异步,那么首先您应该在这里阅读为什么这是个坏主意:应该公开同步方法的异步包装器吗?然后通过删除Task.Run包装并将返回类型更改为void使方法同步,并使用Parallel类或PLINQ库并行调用该方法。下面是一个PLINQ示例:

代码语言:javascript
复制
PlcCollection
    .AsParallel()
    .ForAll(plc => MakeTags(plc.Name, plc.TagFormat));
Console.WriteLine("****PLC Update Complete*****");
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67925235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档