2017-04-06 384 views
0

也有一些是被纏着我了一會兒,在我的代碼我無法理解這種情況發生的東西。C#異步任務等待VS等待

我定義的工作流以從Facebook API提取信息,基本上我有3個不同的async tasks

執行報告

private static async Task<List<DataTypes.ReportRun>> ExecuteMarketingReports(FacebookClient fb, List<DataTypes.Request.Batch> batch_requests) 
{ 
//Do stuff - Make async POST requests to 
//FB to execute reports on FB server side 
} 

Monitorize報告

private static async Task<List<DataTypes.AdReportRun>> MonitorizeMarketingReports(FacebookClient fb, List<DataTypes.ReportRun> tListReportRun) 
{ 
    //Do stuff -- Check if the reports are ready or not, and return a list with status 
} 

GetReportData

private static async Task GetReportData(FacebookClient fb, List<DataTypes.AdReportRun> tListReportRun, DateTime since, DateTime until, string breakdown) 
{ 
//Do stuff - Gets report thata once the reports are finish and create the files 
} 

這是所有其它方法被調用

private static async Task PullInsightsData(FacebookClient fb, List<DataTypes.Request.Batch> batchRequests, DateTime since, DateTime until, string breakdown) 
{ 
    var tResult = new List<DataTypes.AdReportRun>(); 
    int retry = 0; 
     List<DataTypes.AdReportRun> tReportCompleteList = new List<DataTypes.AdReportRun>(); 
     List<DataTypes.AdReportRun> tReportIncompleteList = new List<DataTypes.AdReportRun>(); 


     var report_ids = await ExecuteMarketingReports(fb, batchRequests); 
     Thread.Sleep(20000); // Waits 20 seconds before get the info. 
     do 
     { 
      /*Start monitorizing the reports*/ 
      var tReport_info = await MonitorizeMarketingReports(fb, report_ids); 

      /*Get the reports that are complete*/ 
      tReportCompleteList = tReport_info.Where(x => x.async_percent_completion == 100).ToList(); 

      if (tReportCompleteList.Count > 0) 
       await GetReportData(fb, tReportCompleteList, since, until, breakdown); 

      tReportIncompleteList = tReport_info.Where(x => x.async_percent_completion < 100).ToList(); 

      report_ids = (from x in tReportIncompleteList 
          select new DataTypes.ReportRun { report_run_id = x.id }).ToList(); 

      var sleepTime = TimeSpan.FromSeconds(Math.Pow(2, retry + 1)); 
      Thread.Sleep(sleepTime); 
      retry++; 
     } while (report_ids.Count > 0 && retry < 8); 
} 

我調用這個foreach環路我的主要工作的主要任務,這是發生問題。

for (int i = 0; i < ActiveAdAccounts.Count; i = i + 50) 
{ 
    var AdAccountsSubList = ActiveAdAccounts.Skip(i).Take(50).ToList(); 

    var batchRequests = .... 

await PullInsightsData(fb, batchRequests, (DateTime)since, (DateTime)until, breakdown.Replace(",", "_")); 
    //tTaskList.Add(PullInsightsData(fb, batchRequests, (DateTime)since, (DateTime)until, breakdown.Replace(",", "_"))); 
} 
//Task.WaitAll(tTaskList); 

我不明白爲什麼foreach循環簡化版,繼續使用await控制檯應用程序關閉突然,不應該await「等待」直到任務完成,因此然後進行下一行碼?

我已經解決了這個問題,把所有的任務到一個列表,並等待所有,但我想這個解釋。

[編輯]問題被編輯創建一個最小的可重現的例子。

+1

的可能的複製[如何以及何時使用\'異步\'和\'\伺機'](http://stackoverflow.com/questions/14455293/how-and-when-to-use-async-and等待) –

+0

如果重複,我道歉,我還沒有找到其他有關我的問題。 – bmvr

+0

請包括一個最小的,可重複的例子。你的'for' /'foreach'循環現在沒有'await'。 「await」確實會暫停該方法,直到該任務完成。的 「早歸」 最常見的原因是使用'StartNew'(使用'Task.Run'代替),'ContinueWith'(使用'await'代替),或'異步void'(使用'異步Task'代替)。 –

回答

1

當您在方法中使用await關鍵字時,它將被暫停並將控制權返回給方法的調用方,直到完成等待的方法中的工作。在控制檯應用程序中,主線程將完成其工作,以便程序退出。

就拿下面的程序:

class Program 
{ 
    static void Main() 
    { 
     DoWork(); 
     // Will exit immediately 
    } 

    static async Task DoWork() 
    { 
     await Task.Delay(10000); 
     // Should wait 10 seconds 
    } 
} 

這個程序將立即退出,因爲主線程不awaitDoWork異步方法。

+0

我瞭解異步的await工作,我只是不明白它是如何不按預期在我的循環。想象一下你的例子,你的工作接受了幾個參數,並且你有一個循環,你可以調用await DoWork(args),它會在處理所有任務/循環之前執行每個循環而不退出控制檯應用程序? – bmvr

+0

@BrunoRodrigues鑑於你已經說過,你認爲'await'等待任務完成,否,你*不知道'await'是如何工作的。我建議找到關於這個主題的好教程,並閱讀更多關於它的工作原理。 – Servy

+0

@Servy你能建議嗎? – bmvr