简体   繁体   English

在任务完成之前等待返回

[英]await returns before task completes

I have this async code 我有这个异步代码

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

But what happens is, the I always get 0 count in both the InvoiceRawList and InvoiceDetailRawList . 但是发生的是,我在InvoiceRawListInvoiceDetailRawList总是得到0计数。 What I found is that the method returns before the async lambda completes its processing. 我发现该方法异步lambda完成其处理之前返回。 (In chrome console, the result appears in the network tab, but the debug point in ValidateInsertedDataInRawTablesForInvoiceAsync is hit after that). (在chrome控制台中,结果显示在“网络”标签中,但是此后会在ValidateInsertedDataInRawTablesForInvoiceAsync中点击调试点)。 I am awaiting the Task.Run that I created for this lambda. 我正在等待为此lambda创建的Task.Run What am I doing wrong here? 我在这里做错了什么?

Update after comments 评论后更新

If I do that, it won't compile, I changed it to... 如果这样做,它将无法编译,因此将其更改为...

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

And says cannot await void. 并说不能等待虚无。 Which I know what that means, but then how do I resolve that? 我知道这意味着什么,但是我该如何解决呢? List.ForEach is a void method. List.ForEach是一个无效方法。

You actually want to wait for WHEN ALL of the inner tasks are finished. 您实际上要等待所有内部任务完成。

Task.WhenAll is your friend in this case. 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;
}

You will have to use regular foreach loop if you want to use await inside it. 如果要在其中使用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;
    }

By the way, this code does not make much sense, you are creating invoiceRawList and invoiceDetailRawList just to replace them in every iteration of the loop. 顺便说一句,这段代码没有多大意义,您正在创建invoiceRawListinvoiceDetailRawList只是在循环的每次迭代中替换它们。

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

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