Reputation: 342
I create a list of tasks. As soon as some task in the list completes, I want to process its result (in this case, print the name of a blob).
The code (contained within an async function) reads as follows:
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);
}
The error that is produced: 'Object reference not set to an instance of an object.'
Why is the error produced and how can I fix it?
The task specified in the ContinueWith
method should be executed after the preceding task has finished, so I do not understand what the problem is.
As a side note, the code runs if the statement containing the WriteLine
method is removed.
Upvotes: 0
Views: 166
Reputation: 456477
You shouldn't use ContinueWith
; it's a dangerous, low-level method.
Also, I strongly recommend against the "WhenAny
then remove it from the list" approach. It's almost an antipattern. The code is much simpler if you introduce a helper asynchronous method instead.
On to the Azure-specific problems. First, the way ListBlobsSegmentedAsync
works is that you need to call it one at a time, updating the token with the result of each call, like this:
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);
}
As for the null reference exception, it's most likely because there's a blob that isn't a CloudBlockBlob
, e.g., CloudBlobDirectory
. I'd recommend something like this:
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);
}
Upvotes: 4