【发布时间】:2015-05-27 11:50:58
【问题描述】:
我一直在尝试对我的 CPU 绑定函数采用异步方法来计算一些聚合函数。问题是存在一些死锁(我想),因为计算的时间太不同了。我是这个任务并行世界的真正新手,我也阅读了 Stephem Cleary 的文章,但我仍然不确定这种异步方法的所有方面。 我的代码:
private static void Main(string[] args)
{
PIServer server = ConnectToDefaultPIServer();
AFTimeRange timeRange = new AFTimeRange("1/1/2012", "6/30/2012");
Program p = new Program();
for (int i = 0; i < 10; i++)
{
p.TestAsynchronousCall(server, timeRange);
//p.TestAsynchronousCall(server, timeRange).Wait();-same results
}
Console.WriteLine("Main check-disconnected done");
Console.ReadKey();
}
private async Task TestAsynchronousCall(PIServer server, AFTimeRange timeRange)
{
AsyncClass asyn;
for (int i = 0; i < 1; i++)
{
asyn = new AsyncClass();
await asyn.DoAsyncTask(server, timeRange);
//asyn.DoAsyncTask(server, timeRange);-same results
}
}
public async Task DoAsyncTask(PIServer server, AFTimeRange timeRange)
{
var timeRanges = DivideTheTimeRange(timeRange);
Task<Dictionary<PIPoint, AFValues>>[] tasksArray = new Task<Dictionary<PIPoint, AFValues>>[2];
tasksArray[0] = (Task.Run(() => CalculationClass.AverageValueOfTagPerDay(server, timeRanges[0])));
// tasksArray[1] = tasksArray[0].ContinueWith((x) => CalculationClass.AverageValueOfTagPerDay(server, timeRanges[1]));
tasksArray[1] = (Task.Run(() => CalculationClass.AverageValueOfTagPerDay(server, timeRanges[1])));
Task.WaitAll(tasksArray);
//await Task.WhenAll(tasksArray); -same results
for (int i = 0; i < tasksArray.Length; i++)
{
Program.Show(tasksArray[i].Result);
}
}
我在 AverageValueOfTagPerDay 函数中通过秒表测量时间。这个函数是同步的(有问题吗?)。每个任务需要 12 秒。但是当我取消注释该行并使用 ContinueWith() 方法时,这些任务每个需要 5-6 秒(这是可取的)。怎么可能?
更奇怪的是,当我将 Main() 中的 for 循环设置为 10 时,有时需要 5 秒以及使用 ContinueWith() 时。所以我猜某个地方出现了死锁,但我找不到。
对不起英文,当我尝试解释一些困难时,我仍然遇到问题。
【问题讨论】:
-
您确实意识到您的第一个 for next 将按顺序执行每个迭代。为什么不使用 forparallel ?
-
DoAsyncTask 不完整:
try没有catch也没有finally。它被标记为async,但不使用await。你有多个任务使用PIServer的同一个实例,这个类线程安全吗? -
所以它甚至无法编译。 AsyncTask 不必是异步的。
-
Phillip Stuyck:Main 和 TestAsynchronousCall 中的 for 循环仅用于测试目的——我需要比较每个调用的计算时间。此外,尝试捕获只是因为我忘记删除它。 DoAsyncTask 必须是异步的,因为在我运行 2 个任务之后,我必须等待输入到 Program.Show() 方法的结果。
-
Guillaume:关于 DoAsyncTask 当我删除关键字 async 并将返回类型更改为 void 时,我得到了相同的计算结果。但是感谢您的建议,我没有意识到这一点。此方法是异步的,因为我尝试使用关键字 await(注释行)。关于 PiServer 的好点,我会检查一下!
标签: c# asynchronous async-await task-parallel-library task