使用Task异步处理任务列表.WhenAny



我创建了一个任务列表。一旦列表中的某个任务完成,我就想处理它的结果(在这种情况下,打印blob的名称(。

代码(包含在异步函数中(如下所示:

List<Task<BlobResultSegment>> taskList = new List<Task<BlobResultSegment>>();
BlobContinuationToken token = null;
do
{
taskList.Add(blobContainer.ListBlobsSegmentedAsync(token));
}
while (token != null);

while(taskList.Any())
{
Task<BlobResultSegment> completedTask = await Task.WhenAny(taskList);
await completedTask.ContinueWith(task => {
foreach (IListBlobItem item in task.Result.Results)
{
CloudBlockBlob blob = item as CloudBlockBlob;
Console.WriteLine(blob.Name); // this statement causes the error
}
});
taskList.Remove(completedTask);
}

产生的错误:'对象引用未设置为对象的实例。'

为什么会产生错误,我该如何修复?

ContinueWith方法中指定的任务应该在前一个任务完成后执行,所以我不明白问题出在哪里

附带说明一下,如果删除了包含WriteLine方法的语句,代码就会运行。

您不应该使用ContinueWith;这是一种危险的低级方法。

此外,我强烈建议反对";CCD_ 4然后将其从列表中移除";方法这几乎是一个反模式。如果引入一个helper异步方法,代码会简单得多。

关于Azure的特定问题。首先,ListBlobsSegmentedAsync的工作方式是,您需要一次调用一个,用每次调用的结果更新令牌,如下所示:

List<IListBlobItem> blobs = new();
BlobContinuationToken token = null;
do
{
var result = await blobContainer.ListBlobsSegmentedAsync(token);
blobs.AddRange(result.Results);
token = result.ContinuationToken;
} while (token != null);
foreach (var item in blobs)
{
CloudBlockBlob blob = item as CloudBlockBlob;
Console.WriteLine(blob.Name);
}

至于null引用异常,很可能是因为有一个blob不是CloudBlockBlob,例如CloudBlobDirectory。我推荐这样的东西:

foreach (var item in blobs)
{
if (item is CloudBlob blob)
Console.WriteLine(blob.Name);
else if (item is CloudBlobDirectory dir)
Console.WriteLine("Dir: " + dir.Prefix);
}

最新更新