[英]await returns before task completes
我有这个异步代码
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;
}
但是发生的是,我在InvoiceRawList
和InvoiceDetailRawList
总是得到0计数。 我发现该方法在异步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是一个无效方法。
您实际上要等待所有内部任务完成。
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;
}
如果要在其中使用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;
}
顺便说一句,这段代码没有多大意义,您正在创建invoiceRawList
和invoiceDetailRawList
只是在循环的每次迭代中替换它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.