0

There is something that is bugging me for a while, something that happen in my code I can't understand.

I've defined a workflow to extract information from the Facebook API, basically I have 3 different async tasks.

Execute Reports

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 Reports

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
}

This is the main Task where all the other methods are called

 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);
}

I call my Main task in this foreach loop, and this is where the problem occurs.

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);

I don't understand why the foreach loop does't continue using the await the console application closes suddenly, shouldn't await "wait" until the task is finish and so then proceed to the next line of code?

I've solved the problem putting all the tasks into a list and waiting for all, but I would like an explanation for this.

[EDITED] Question was edited to create a minimal reproducible example.

bmvr
  • 817
  • 2
  • 9
  • 25
  • 1
    Possible duplicate of [How and When to use \`async\` and \`await\`](http://stackoverflow.com/questions/14455293/how-and-when-to-use-async-and-await) – BJ Myers Apr 06 '17 at 17:31
  • If duplicated I apologize, I haven't find other questions related to mine. – bmvr Apr 06 '17 at 17:35
  • Please include a minimal, reproducible example. There's no `await` in your `for`/`foreach` loop right now. `await` does in fact pause the method until that task completes. The most common causes of "early return" are using `StartNew` (use `Task.Run` instead), `ContinueWith` (use `await` instead), or `async void` (use `async Task` instead). – Stephen Cleary Apr 06 '17 at 17:37
  • @StephenCleary I would include it but it's way to complex to include all the code into this question. I'm not sure how to make it more clear to you guys. – bmvr Apr 06 '17 at 17:40
  • @BrunoRodrigues What you need to do is create a *minimal* reproducible example. In other words, delete code (or replace with stub operations like `Task.Delay`) until it is as small as you can get it. At each step, verify that the incorrect behavior still happens. [More info here](https://stackoverflow.com/help/mcve). – Stephen Cleary Apr 06 '17 at 18:29
  • I've edited my question to create a minimal reproducible example. I Hope you guys understand what I mean this time. – bmvr Apr 07 '17 at 09:27
  • 1
    Side comment: in async functions, do not call `Thread.Sleep()`. Instead do `await Task.Delay()`. `Sleep` will synchronously block your thread and defeat the purpose of using async/await in the first place. `Task.Delay()` will allow you to "wait for some time to go by" in an async friendly way. – Brandon Apr 07 '17 at 15:28
  • check this one for Console App https://stackoverflow.com/questions/9208921/cant-specify-the-async-modifier-on-the-main-method-of-a-console-app – Malik Aqib Mar 10 '18 at 21:16

0 Answers0