【发布时间】:2021-05-14 12:27:45
【问题描述】:
我创建了一个任务列表。一旦列表中的某个任务完成,我想处理它的结果(在这种情况下,打印一个 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 方法的语句,则代码运行。
【问题讨论】:
-
很可能,item 不是 CloudBlockBlob 对象。它甚至可以为空。这取决于 BlobResultSegment.Results 的实现。
-
嗯,你还没有告诉发生这种情况的行。您发布的代码有多个可能发生空引用异常的点。
task.Result.Results如果task.Result是null这将抛出上述错误。item as CloudBlockBlob这将返回null如果item不是CloudBlockBlob类型,如果发生这种情况下一行blob.Name将抛出上述错误。 -
你为什么还要在这里使用
ContinueWith?它不应该与错误有关,但你只是让你的逻辑更复杂。您已经等待任务,只需在其下方添加您需要的代码,它也会在任务完成后发生。正如@Rubidium37 所说,您看到的问题可能是由于as演员。您应该从不使用as,然后“假设”它是那种类型,因为as可以返回null。如果您确定对象必须是给定类型,或者处理它可能是另一种类型的情况,请使用普通转换。 -
出于好奇,您的代码暗示您希望同时运行所有任务,并按顺序运行它们的所有延续(一个接一个的延续,没有重叠)。这是故意的吗?
标签: c# async-await task