2017-02-17 81 views
2

我在測量異步代碼片段的執行時間方面遇到問題,所以我創建了一個控制檯應用程序,以便於測試。我正試圖查看下載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'方法。 –

回答

1

這個問題似乎是與線

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