C# 在任务完成之前等待返回

C# 在任务完成之前等待返回,c#,asynchronous,lambda,async-await,task,C#,Asynchronous,Lambda,Async Await,Task,我有这个异步代码 private async Task<InvalidInvoiceViewModel> ValidateInsertedDataInRawTables(string uploadPath, long batchId) { var direcotryPath = Path.Combine(uploadPath, batchId.ToString()); var allFiles = Directory.GetFiles(dire

我有这个异步代码

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

并说不能等待空虚。我知道这意味着什么,但我该怎么解决呢?List.ForEach是一个void方法。

如果要在其中使用wait,则必须使用常规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;
    }
private async Task validateInsertedDaintaRawtables(字符串上传路径,长batchId)
{
var direcotryPath=Path.Combine(uploadPath,batchId.ToString());
var allFiles=Directory.GetFiles(direcotryPath);
var invoiceRawList=新列表();
var invoiceDetailRawList=新列表();
等待任务。运行(异步()=>
{
foreach(所有文件中的var文件)
{
var fileName=Path.GetFileNameWithoutExtension(文件);
开关(文件名)
{
案例“发票”:
invoiceRawList=Wait ValidateInsertedTainRawTablesForInvoiceAsync(batchId);
打破
案例“发票详情”:
invoiceDetailRawList=等待ValidateInsertedTainRawTablesForInvoiceDetailAsync(batchId);
打破
}
}
});
var invalidInvoiceViewModel=新的invalidInvoiceViewModel
{
发票列表=发票列表,
InvoiceDetailRawList=InvoiceDetailRawList
};
返回voiceview模型;
}

顺便说一句,这段代码没有多大意义,您正在创建
invoiceRawList
invoiceDetailRawList
,只是为了在循环的每个迭代中替换它们。

您实际上希望等待所有内部任务完成

任务。在这种情况下,whalll
是您的朋友

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;
}
private async Task validateInsertedDaintaRawtables(字符串上传路径,长batchId)
{
var direcotryPath=Path.Combine(uploadPath,batchId.ToString());
var allFiles=Directory.GetFiles(direcotryPath);
var invoiceRawList=新列表();
var invoiceDetailRawList=新列表();
列出任务=所有文件。选择(文件=>Task.Run(异步()=>
{
var fileName=Path.GetFileNameWithoutExtension(文件);
开关(文件名)
{
案例“发票”:
invoiceRawList=Wait ValidateInsertedTainRawTablesForInvoiceAsync(batchId);
打破
案例“发票详情”:
invoiceDetailRawList=等待ValidateInsertedTainRawTablesForInvoiceDetailAsync(batchId);
打破
}
})).ToList();
等待任务。何时(任务);
var invalidInvoiceViewModel=新的invalidInvoiceViewModel
{
发票列表=发票列表,
InvoiceDetailRawList=InvoiceDetailRawList
};
返回voiceview模型;
}

您没有等待ForEach循环体,它也是异步的。每个文件都设置了invoiceRawList和invoiceDetailRawList@Evk:我这样做了,但现在它甚至无法编译!当然,它不会编译。ForEach是一种你根本不能等待的无效方法——不是这样。替换为常规foreach,或将所有任务放入列表中,并使用Wait Task等待所有任务。Whalll.我知道,但我们在每个文件夹中始终只有两个文件,
invoice
invoicedetails
。然后重新编写代码,说明这是事实而不是幸运的结果。如何验证。。。方法知道要处理的文件吗?您只需将batchId传递给他们。看起来很脆弱structure@SirRufo:实际上,它们是两种不同的方法,一种用于
发票
文件
validateInsertedTainRawTablesForInvoiceAsync
,另一种用于
invoicedetail
文件
validateInsertedTainRawTablesForInvoiceDetailAsync
。你还认为这是个问题吗?这些方法是如何知道上传路径的?
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;
}