Azure Blob容器遍历异常:控制台应用调用ListBlobsSegmentedAsync后进程以代码0终止
问题根源分析
你的问题核心出在异步方法的调用与等待逻辑上:
- 你定义的
GetBlobFileProperties是async void类型,这种返回值主要用于UI事件处理场景,在控制台应用中调用时,主线程不会等待它的异步操作完成。 - Main方法是同步执行的,调用
analyser.GetBlobFileProperties()后会立刻执行完毕,导致整个进程直接退出(返回code 0),此时ListBlobsSegmentedAsync的异步操作还没来得及完成就被终止了。
解决方案
我们需要调整异步方法的定义和调用方式,确保主线程等待异步操作完成,同时完善Blob的分段遍历逻辑(避免只获取第一页数据):
1. 修改异步方法的返回类型
把async void改成async Task,这样我们可以在调用时用await等待它执行完成:
public class AzureStorageAnalyser { public async Task GetBlobFileProperties() { try { string storageConnection = "DefaultEndpointsProtocol=https;AccountName=****;AccountKey=****;EndpointSuffix=core.windows.net"; CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(storageConnection); CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient(); CloudBlobContainer blobContainer = cloudBlobClient.GetContainerReference("users"); BlobContinuationToken blobContinuationToken = null; List<string> fileUris = new List<string>(); // 循环获取所有分段的Blob,直到没有更多数据 do { // 使用完整重载确保扁平化列出所有Blob(不显示虚拟目录) var resultSegment = await blobContainer.ListBlobsSegmentedAsync( prefix: null, useFlatBlobListing: true, blobListingDetails: BlobListingDetails.None, maxResults: null, currentToken: blobContinuationToken, options: null, operationContext: null); blobContinuationToken = resultSegment.ContinuationToken; foreach (var blobItem in resultSegment.Results) { // 确保处理的是Blob而非虚拟目录 if (blobItem is CloudBlockBlob blob) { fileUris.Add(blob.StorageUri.PrimaryUri.ToString()); Console.WriteLine($"已获取Blob: {blob.Name}"); } } } while (blobContinuationToken != null); Console.WriteLine($"共获取到 {fileUris.Count} 个Blob资源"); } catch (Exception ex) { Console.WriteLine($"发生错误: {ex.Message}"); // 打印堆栈信息便于排查深层问题 Console.WriteLine(ex.StackTrace); } } }
2. 修改Main方法为异步入口
从C# 7.1开始,控制台应用支持async Task Main作为入口方法,这样我们可以直接等待异步操作完成:
static async Task Main(string[] args) { AzureStorageAnalyser analyser = new AzureStorageAnalyser(); await analyser.GetBlobFileProperties(); // 可选:添加等待输入,避免程序执行完后窗口立刻关闭 Console.WriteLine("\n按任意键退出..."); Console.ReadKey(); }
额外说明
- 我添加了
do-while循环来处理Blob的分页返回,当容器中Blob数量较多时,ListBlobsSegmentedAsync会分段返回结果,只调用一次只能拿到第一页数据。 - 增加了
CloudBlockBlob的类型判断,避免处理容器中的虚拟目录(如果存在的话)。 - 在catch块中添加了堆栈信息打印,方便你排查可能的存储账户连接、权限等深层问题。
内容的提问来源于stack exchange,提问作者sm101
相关产品推荐
相关产品推荐

