测量异步代码片段的执行时间

问题描述:

我在测量异步代码片段的执行时间方面遇到问题,所以我创建了一个控制台应用程序,以便于测试。我正试图查看下载200MB文件所需的时间是否与程序的输出相符。但是,在代码片段的第一个命令以输出“22 ms”结束后,该应用会立即停止执行。任何想法为什么发生这种情况?测量异步代码片段的执行时间

在我的真实应用程序中,GUI本质上是多线程的,测量时间也是不现实的。我尝试将“Task.Delay”调用插入片段,它似乎对测量值没有影响。

为了简洁起见,我从真实应用程序缩短了代码。任何想法为什么这不起作用?如何衡量异步代码片段的时间执行的替代想法?

class Program 
{ 
    static void Main(string[] args) 
    { 
     MainAsync().GetAwaiter().GetResult(); 
    } 

    private static async Task MainAsync() 
    { 
     var httpClient = new HttpClient(); 

     await MeasureExecutionTimeAsync(
      async() => { 
       // download a 200MB file 
       var response = await httpClient.GetAsync("http://web4host.net/200MB.zip"); 

       // this never gets executed 
       var array = await response.Content.ReadAsByteArrayAsync(); 
       File.WriteAllBytes("C:/mytmp/bytefile.xxx", array); 
      } 
     ); 
    } 

    private static async Task MeasureExecutionTimeAsync(Action measuredAction) 
    { 
     var stopwatch = new Stopwatch(); 
     stopwatch.Start(); 

     await Task.Run(measuredAction); 

     stopwatch.Stop(); 

     Console.WriteLine(stopwatch.ElapsedMilliseconds + " ms"); 
    } 
} 
+1

这是问题的一个相当普遍的 “一'Task'内'Task'”。你现在拥有的东西的方式不是测量执行内部任务的时间,而是测量执行的外部任务(它只是创建内部任务)的时间,当然这几乎为零。 – sellotape

+0

主要问题是由于使用'async void'。通过将'async' lambda传递给'Action'委托参数,该代码正在指示编译器编写'async void'方法。 –

这个问题似乎是与线

await Task.Run(measuredAction); 

试试这个

private static async Task MainAsync() 
    { 
     var httpClient = new HttpClient(); 

     Func<Task> action = async() => 
     { 
      var response = await httpClient.GetAsync("http://web4host.net/200MB.zip").ConfigureAwait(false); 

      // this never gets executed 
      var array = await response.Content.ReadAsByteArrayAsync(); 
      File.WriteAllBytes("C:/mytmp/bytefile.xxx", array); 
      return; 
     }; 

     await MeasureExecutionTimeAsync(action); 
    } 

    private static async Task MeasureExecutionTimeAsync(Func<Task> measuredAction) 
    { 
     var stopwatch = new Stopwatch(); 
     stopwatch.Start(); 

     await measuredAction.Invoke(); 

     stopwatch.Stop(); 

     Console.WriteLine(stopwatch.ElapsedMilliseconds + " ms"); 
    } 
+5

或简单地'await measuredAction();'而不是使用'Invoke()'。 – sellotape