await Task.WhenAll vs ..select(async .. => await)

Roe*_*t M 7 c# asynchronous

只是一个简单的问题.我们在这里有一些误解.

我们有:

var tasks = files.Select(async fileName => await IngestFileAsync(container, fileName));
var results = await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)

我说第一行仍然是并发的,但我的同事说不然.此外,他说第二个await没有意义,因为所有行动都已经完成.

这个代码是相同的:

var tasks = files.Select(fileName => IngestFileAsync(container, fileName));
var results = await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)

如:

var tasks = files.Select(async fileName => await IngestFileAsync(container, fileName));
var results = Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)

有人可以为此发光吗?

干杯.

补充:oke,所以它会并发运行.

但是,有人可以添加一些额外的信息这些代码片段之间的差异:https : //dotnetfiddle.net/lzv2B7 https://dotnetfiddle.net/dMusus

(注意第16行,asyncawait).这两个之间有什么区别吗?我期望的是,使用异步和等待它将直接启动,并且没有,它将在它开始时启动Await Task.WhenAll(tasks);

添加清晰度 - 这是我的代码 - :

   private async Task<Result> IngestFilesAsync(ICloudBlobContainer container, IEnumerable<string> files)
    {
        _logger.LogDebug("Start IngestFilesAsync");

        var tasks = files.Select(fileName => IngestFileAsync(container, fileName));
        var results = await Task.WhenAll(tasks);

        _logger.LogDebug("All tasks completed");

        if (results.Any(t => t.IsFailure))
        {
            return Result.Fail(string.Join(",", results.Select(f => f.Error)));
        }

        return Result.Ok();
    }

    private async Task<Result> IngestFileAsync(ICloudBlobContainer container, string fileName)
    {
        _logger.LogDebug("Start IngestFileAsync");
        var blob = container.GetBlockBlobReference(fileName);

        _logger.LogDebug("Blob retrieved");

        if (await blob.ExistsAsync())
        {
            using (var memoryStream = new MemoryStream())
            {
                _logger.LogDebug("Start download to stream");
                await blob.DownloadToStreamAsync(memoryStream);
                _logger.LogDebug("To mem downloaded");

                _logger.LogDebug("Start ftp-upload");

                return await _targetFTP.UploadAsync(memoryStream, fileName);
            }
        }

        _logger.LogWarning("Blob does not exists");

        return Result.Fail($"Blob '{fileName}' does not exist");
    }
Run Code Online (Sandbox Code Playgroud)

哪里_targetFTP.UploadAsync(memoryStream, fileName);又是一个任务等等.

小智 9

async x => await f()创建一个返回任务的匿名函数.该任务有效地包装了由f以下创建的:它将在之后直接完成.特别是,此匿名函数会尽快返回正在进行的任务.

.Select根据枚举类型是否是任务之一,行为不同.当第一个返回的任务仍在进行时,它允许直接获取下一个结果.

代码片段不是100%相同,但您所询问的差异不存在.

差异很小; 最明显的变化可能是异常处理.假设您有两个尚未实现的功能:

Task Sync() => throw new NotImplementedException();
async Task Async() => throw new NotImplementedException();
Run Code Online (Sandbox Code Playgroud)

在这里,var task = Sync();显然立即失败了.但是var task = Async();有所不同:成功.async此处的关键字强制创建任务,捕获抛出的异常.

这同样的区别也适用于.Select(x => Sync())VS .Select(async x => await Sync()).