只是一个简单的问题。我们在这里有一些误解。
我们有:
var tasks = files.Select(async fileName => await IngestFileAsync(container, fileName));
var results = await Task.WhenAll(tasks);
我说第一行仍然是并发的,但我的同事说不然。此外,他说第二个await
没有任何意义,因为所有
行动已经完成。
这个代码是相同的:
var tasks = files.Select(fileName => IngestFileAsync(container, fileName));
var results = await Task.WhenAll(tasks);
为:
var tasks = files.Select(async fileName => await IngestFileAsync(container, fileName));
var results = Task.WhenAll(tasks);
有人可以为此发光吗?
欢呼声。
加入: 哦,它会并发运行。
但是,有人可以添加一些额外的信息,这些代码片段之间的区别是什么: https://dotnetfiddle.net/lzv2B7 https://dotnetfiddle.net/dMusus
(注意第16行,async
和await
)。这两个之间有什么区别吗?
我期望的是与异步并等待它将直接启动,而不是,它将在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");
}
其中_targetFTP.UploadAsync(memoryStream, fileName);
又是一项任务等等。
答案 0 :(得分:9)
async x => await f()
创建一个返回任务的匿名函数。该任务有效地包装了由f
创建的那个:它将在之后直接完成。特别是,此匿名函数会尽快返回正在进行的任务。
.Select
的行为不同。当第一个返回的任务仍在进行时,它允许直接获取下一个结果。
代码片段并非100%相同,但您所询问的差异不存在。
差异很小;最明显的变化可能是异常处理。假设您有两个尚未实现的函数:
Task Sync() => throw new NotImplementedException();
async Task Async() => throw new NotImplementedException();
在这里,var task = Sync();
显然会立即失败。但是var task = Async();
是不同的:成功了。这里的async
关键字强制创建一个任务,捕获抛出的异常。
同样的区别也适用于.Select(x => Sync())
vs .Select(async x => await Sync())
。