2017-04-20 167 views
-1

之前,我有這樣的異步代碼等待返回任務完成

private async Task<InvalidInvoiceViewModel> ValidateInsertedDataInRawTables(string uploadPath, long batchId) 
    { 
     var direcotryPath = Path.Combine(uploadPath, batchId.ToString()); 
     var allFiles = Directory.GetFiles(direcotryPath); 
     var invoiceRawList = new List<InvoiceRaw>(); 
     var invoiceDetailRawList = new List<InvoiceDetailRaw>(); 
     await Task.Run(() => allFiles.ToList().ForEach(async file => 
     { 
      var fileName = Path.GetFileNameWithoutExtension(file); 
      switch (fileName) 
      { 
       case "invoice": 
        invoiceRawList = await ValidateInsertedDataInRawTablesForInvoiceAsync(batchId); 
        break; 
       case "invoicedetails": 
        invoiceDetailRawList = await ValidateInsertedDataInRawTablesForInvoiceDetailAsync(batchId); 
        break; 
      } 
     })); 
     var invalidInvoiceViewModel = new InvalidInvoiceViewModel 
     { 
      InvoiceRawList = invoiceRawList , 
      InvoiceDetailRawList = invoiceDetailRawList 
     }; 
     return invalidInvoiceViewModel; 
    } 

但發生的事情是,在我總是得到0計數在InvoiceRawListInvoiceDetailRawList兩者。我發現該方法返回之前異步lambda完成其處理。 (在Chrome控制檯中,結果出現在網絡選項卡中,但在此之後會觸發ValidateInsertedDataInRawTablesForInvoiceAsync中的調試點)。我正在等待爲此lambda創建的Task.Run。我在這裏做錯了什麼?評論

如果我這樣做,以後

更新,它不會編譯,我把它改成...

private async Task<InvalidInvoiceViewModel> ValidateInsertedDataInRawTables(string uploadPath, long batchId) 
    { 
     var direcotryPath = Path.Combine(uploadPath, batchId.ToString()); 
     var allFiles = Directory.GetFiles(direcotryPath); 
     var invoiceRawList = new List<InvoiceRaw>(); 
     var invoiceDetailRawList = new List<InvoiceDetailRaw>(); 
     await Task.Run(async() => await allFiles.ToList().ForEach(async file => 
     { 
      var fileName = Path.GetFileNameWithoutExtension(file); 
      switch (fileName) 
      { 
       case "invoice": 
        invoiceRawList = await ValidateInsertedDataInRawTablesForInvoiceAsync(batchId); 
        break; 
       case "invoicedetails": 
        invoiceDetailRawList = await ValidateInsertedDataInRawTablesForInvoiceDetailAsync(batchId); 
        break; 
      } 
     })); 
     var invalidInvoiceViewModel = new InvalidInvoiceViewModel 
     { 
      InvoiceRawList = invoiceRawList , 
      InvoiceDetailRawList = invoiceDetailRawList 
     }; 
     return invalidInvoiceViewModel; 
    } 

,並說不能等待無效。我知道這意味着什麼,但是我該如何解決這個問題? List.ForEach是一個無效的方法。

+5

您並未等待您的ForEach循環體,它也是異步的。 – Evk

+1

並**每個**文件設置invoiceRawList和invoiceDetailRawList –

+0

@Evk:我做到了,但現在它甚至不會編譯! – Razort4x

回答

0

如果你想在裏面使用await,你將不得不使用普通的foreach循環。

private async Task<InvalidInvoiceViewModel> ValidateInsertedDataInRawTables(string uploadPath, long batchId) 
    { 
     var direcotryPath = Path.Combine(uploadPath, batchId.ToString()); 
     var allFiles = Directory.GetFiles(direcotryPath); 
     var invoiceRawList = new List<InvoiceRaw>(); 
     var invoiceDetailRawList = new List<InvoiceDetailRaw>(); 
     await Task.Run(async() => 
     { 
      foreach(var file in allFiles) 
      { 
       var fileName = Path.GetFileNameWithoutExtension(file); 
       switch (fileName) 
       { 
        case "invoice": 
         invoiceRawList = await ValidateInsertedDataInRawTablesForInvoiceAsync(batchId); 
         break; 
        case "invoicedetails": 
         invoiceDetailRawList = await ValidateInsertedDataInRawTablesForInvoiceDetailAsync(batchId); 
         break; 
       } 
      } 
     }); 
     var invalidInvoiceViewModel = new InvalidInvoiceViewModel 
     { 
      InvoiceRawList = invoiceRawList, 
      InvoiceDetailRawList = invoiceDetailRawList 
     }; 
     return invalidInvoiceViewModel; 
    } 

順便說一句,這個代碼並沒有太大的意義,要創建invoiceRawListinvoiceDetailRawList只是以取代他們在循環的每次迭代。

+0

我知道,但是我們只會在每個文件夾中總是有2個文件,'invoice'和'invoicedetails'。 – Razort4x

+0

然後重寫你的代碼,這是一個事實,而不是幸運的拍攝 –

+0

Validate ...方法如何知道要處理的文件?你只需將batchId傳遞給他們。似乎是非常脆弱的結構 –

2

您實際上想等待所有內部任務完成時。

Task.WhenAll是你在這種情況下的朋友。

private async Task<InvalidInvoiceViewModel> ValidateInsertedDataInRawTables(string uploadPath, long batchId) 
{ 
    var direcotryPath = Path.Combine(uploadPath, batchId.ToString()); 
    var allFiles = Directory.GetFiles(direcotryPath); 
    var invoiceRawList = new List<InvoiceRaw>(); 
    var invoiceDetailRawList = new List<InvoiceDetailRaw>(); 

    List<Task> tasks = allFiles.Select(file => Task.Run(async() =>  
    { 
     var fileName = Path.GetFileNameWithoutExtension(file); 
     switch (fileName) 
     { 
      case "invoice": 
       invoiceRawList = await ValidateInsertedDataInRawTablesForInvoiceAsync(batchId); 
       break; 
      case "invoicedetails": 
       invoiceDetailRawList = await ValidateInsertedDataInRawTablesForInvoiceDetailAsync(batchId); 
       break; 
     } 
    })).ToList(); 

    await Task.WhenAll(tasks); 

    var invalidInvoiceViewModel = new InvalidInvoiceViewModel 
    { 
     InvoiceRawList = invoiceRawList, 
     InvoiceDetailRawList = invoiceDetailRawList 
    }; 
    return invalidInvoiceViewModel; 
}