繁体   English   中英

在任务完成之前等待返回

[英]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;
    }

但是发生的是,我在InvoiceRawListInvoiceDetailRawList总是得到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;
    }

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM