当创建需要执行的任务列表时,其中一些任务可能会失败,但不应停止代码的执行,我想出了仅在出错的任务上使用 continuewith ,但是当在任务集合上调用 Task.WhenAll() 时它抛出任务被取消的异常:
使用的代码片段:
var deletOldFiles = dbDraft
?.Documents?.Select(s => s.Id)
.Select(id =>
_fileStorage
.DeleteFileAsync(
_fileStorageConfiguration.DefaultFileCollectionName,
id,
cancellationToken
)
.ContinueWith(
t =>
{
_logger.LogError(
"Could not delete document with identifier: {id}",
id
);
},
TaskContinuationOptions.OnlyOnFaulted
)
);
if (deletOldFiles is not null)
await Task.WhenAll(deletOldFiles);
即使调用Task.WhenAll时,主任务DeleteFileAsync()执行成功,但Task.WhenAll抛出异常。
当我删除ContinueWith()调用时,代码工作正常并且Task.WhenAll()完成。但我希望如果某些文件删除失败,继续删除其他文件。
ContinueWith()
当任务的执行条件不满足时,即在您的情况下,当前面的任务完成而没有错误时,任务将被取消。
并且由于您返回 ContinueWith()
任务,因此 Task.WhenAll
方法对所有延续进行操作,而不是对原始任务进行操作。
快速修复 - 返回原始任务,忽略取消:
var deletOldFiles = dbDraft
?.Documents?.Select(s => s.Id)
.Select(id =>
{
var t = _fileStorage
.DeleteFileAsync(
_fileStorageConfiguration.DefaultFileCollectionName,
id,
cancellationToken
);
t.ContinueWith(
t =>
{
_logger.LogError(
"Could not delete document with identifier: {id}",
id
);
}, TaskContinuationOptions.OnlyOnFaulted);
return t;
}
);
if (deletOldFiles is not null)
await Task.WhenAll(deletOldFiles);
有几个时刻需要提及:
Enumerable.Select
打电话两次吗?一次就够了。dbDraft
的零传播?可以为空吗,
认真的吗?