2017-04-06 24 views
0

しばらく私を盗んでいるものがあります。私のコードで何か起こることがわかりません。C#非同期タスク待機待ちvs待ち受け

私はFacebook APIから情報を抽出するためのワークフローを定義しましたが、基本的には3種類のasync tasksがあります。

Monitorizeが

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 
} 

このGetReportData

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 
} 

を報告したレポート

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 
} 

を実行します他のすべてのメソッドが

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を、使用し続けるので、その後の次の行に進みdoes'tなぜ私は理解していませんコード?

すべてのタスクをリストに入れてすべてを待っている問題を解決しましたが、これについて説明したいと思います。

[編集済み]最小限の再現可能な例を作成するために質問を編集しました。

+1

[\ async \と\ 'await \]を使用する方法とタイミング(http://stackoverflow.com/questions/14455293/how-and-when-to-use-async-and)の可能な複製-await) –

+0

重複してお詫び申し上げますのであれば、私に関連する他の質問はありません。 – bmvr

+0

最小限で再現可能な例を含めてください。あなたの 'for' /' foreach'ループには 'await'がありません。 'await'は、実際には、そのタスクが完了するまでメソッドを一時停止します。 "早期復帰"の最も一般的な原因は、 'StartNew'(代わりに' Task.Run'を使用)、 'ContinueWith'(代わりに' await'を使用)、 'async void'(代わりに' async Task'を使用)です。 –

答えて

1

メソッドでawaitキーワードを使用すると、そのメソッドは中断され、待っているメソッドの処理が完了するまで、コントロールはasyncメソッドの呼び出し元に戻されます。コンソールアプリケーションでは、メインスレッドは作業を終了し、プログラムは終了します。例えば

テイク以下のプログラム:メインスレッドがawaitDoWork非同期メソッドいないため、このプログラムは、すぐに終了します

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

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

+0

私はどのように非同期待ちですか私のループで期待どおりに動作しないのは分かりません。あなたの仕事はいくつかの引数を受け取り、DoWork(args)を待っているループを持っています。すべてのタスク/ループを処理する前に、コンソールアプリケーションを終了せずにすべてのループを行いますか? – bmvr

+0

@BrunoRodrigues「待っています」と答えていることを考えれば、「待っています」ということは理解できません。私は主題に関する良いチュートリアルを見つけて、それがどのように機能するかについてもっと読むことをお勧めします。 – Servy

+0

@Servyあなたは1つを提案できますか? – bmvr