异步任务需要花费太多时间

时间:2015-03-24 08:36:59

标签: c# asynchronous async-await task-parallel-library task

大家好,我一直在尝试对我的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秒(这是可取的)。这怎么可能? 更奇怪的是,当我在10上的Main()中设置for循环时,有时需要5秒以及使用ContinueWith()时。所以我猜某个地方已陷入僵局,但我无法找到。 对不起英语,当我尝试解释一些困难时,我仍然有问题做好事。 干杯 更新我删除了过时的尝试,以便更清晰

1 个答案:

答案 0 :(得分:3)

  

大家好,我一直在尝试对我的CPU绑定函数进行异步处理,计算一些聚合函数。

“Asynchronous”和“CPU-bound”不是一起使用的术语。如果你有一个CPU绑定的进程,那么你应该使用并行技术(Parallel,Parallel LINQ,TPL Dataflow)。

  

我是这个任务并行世界的新手,我也读过Stephem Cleary文章,但我仍然不确定这种异步方法的所有方面。

可能是因为我没有在我的任何文章或博文中介绍并行技术。 :)我在书中覆盖了它们,但不在线。我的在线工作主要关注异步,这是基于I / O的操作的理想选择。

要解决您的问题,您应该使用并行方法:

public Dictionary<PIPoint, AFValues>[] DoTask(PIServer server, AFTimeRange timeRange)
{
  var timeRanges = DivideTheTimeRange(timeRange);
  var result = timeRanges.AsParallel().AsOrdered().
      Select(range => CalculationClass.AverageValueOfTagPerDay(server, range)).
      ToArray();
  return result;
}

当然,这种方法假设PIServer是线程安全的。它还假设“服务器”类没有进行I / O操作;如果有,那么TPL Dataflow可能是比Parallel LINQ更好的选择。

如果您打算在UI应用程序中使用此代码并且不想阻止UI线程,那么您可以异步调用代码,如下所示:

var results = await Task.Run(() => DoTask(server, timeRange));
foreach (var result in results)
  Program.Show(result);