.NET Framework 4.7.2 WinForms读取Azure Blob时PerTypeValues`1初始化异常求助
问题详情
基于.NET Framework 4.7.2的WinForms应用,上传Blob到Azure存储账户功能正常,但调用OpenRead()方法流式读取Blob时,抛出错误:'PerTypeValues`1'的类型初始值设定项引发异常。
流式读取实现代码
Public Function StreamFileFromAzureStorageAcct(ByVal clientLocalFilePath As String, ByVal containerDestName As String, ByRef strReturn As String) As StreamReader Dim strReturn As String = String.Empty Dim textInStream As Stream = Nothing Dim textIn As StreamReader = Nothing Dim connectionString As String = Nothing Try connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}", modConfigSettings.AzureStorageAcctName, modConfigSettings.AzureStorageAcctKey, modConfigSettings.AzureStorageAcctURL) Dim Container As BlobContainerClient = New BlobContainerClient(connectionString, containerDestName) Dim BlobClient As BlobClient = Container.GetBlobClient(Path.GetFileName(clientLocalFilePath)) Dim readOptions As BlobOpenReadOptions = New BlobOpenReadOptions(False) readOptions.Position = 0 ''Azure Storage Acct Read call returns a Stream textInStream = BlobClient.OpenRead(readOptions) '' Pass the Stream to a StreamReader to stay inline with existing code. textIn = New StreamReader(textInStream) strReturn = "Success" Return textIn Catch er As Exception strReturn = String.Format("Failed to Stream from Storage Account: {0}-File:{1}-connectionString: {2}-{3}", er.Message, Path.GetFileName(clientLocalFilePath), connectionString, er.StackTrace) End Try Return Nothing End Function
捕获到的错误栈
从存储账户流式读取失败:'PerTypeValues`1'的类型初始值设定项引发异常。- at System.SpanHelpers.IsReferenceOrContainsReferencesT at Azure.Storage.Blobs.BlobRestClient.get_ResponseClassifier200() at Azure.Storage.Blobs.BlobRestClient.CreateGetPropertiesRequest(String snapshot, String versionId, Nullable1 timeout, String leaseId, String encryptionKey, String encryptionKeySha256, StringencryptionAlgorithm,String ifTags, RequestConditions requestConditions, RequestContext context) at Azure.Storage.Blobs.BlobRestClient.GetProperties(String snapshot, String versionId, Nullable1 timeout, String leaseId, String encryptionKey, String encryptionKeySha256, String encryptionAlgorithm, String ifTags, RequestConditions requestConditions, RequestContext context) at Azure.Storage.Blobs.Specialized.BlobBaseClient.d__124.MoveNext() --- End of stack trace from previous location where exception was throw --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) atSystem.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) atAzure.Storage.Blobs.Specialized.BlobBaseClient.d__98.MoveNext() --- End of stack trace from previous location where exception was thrown --- atSystem.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Tasktask) atAzure.Storage.Blobs.Specialized.BlobBaseClient.OpenRead(BlobOpenReadOptions options, CancellationToken cancellationToken) at DBAccessObjects.RemFredDataAdmin.StreamFileFromAzureStorageAcct(StringclientLocalFilePath, String containerDestName, String& strReturn) in C:\Users\csale\source\Workspaces\Application Server\FredServer\DBAccessObjects\RemFredDataAdmin.vb:line 15904
解决方案
1. 适配Azure存储SDK版本
.NET Framework 4.7.2对较新的Azure.Storage.Blobs SDK兼容性有限,建议降级到12.17.0及以下版本,该版本对.NET Framework支持更完善,避免SDK内部使用.NET Core专属API导致的初始化异常。
2. 补充System.Memory组件
错误中的SpanHelpers属于System.Memory模块,.NET Framework 4.7.2原生未完整支持,需安装System.Memory NuGet包(推荐版本4.5.4+),补充缺失的类型和方法。
3. 改用异步读取方法
尝试使用异步版本OpenReadAsync()替代同步调用,规避线程或初始化逻辑冲突,修改后的示例代码:
Public Async Function StreamFileFromAzureStorageAcctAsync(ByVal clientLocalFilePath As String, ByVal containerDestName As String, ByRef strReturn As String) As Task(Of StreamReader) Dim textInStream As Stream = Nothing Dim textIn As StreamReader = Nothing Dim connectionString As String = Nothing Try connectionString = String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}", modConfigSettings.AzureStorageAcctName, modConfigSettings.AzureStorageAcctKey, modConfigSettings.AzureStorageAcctURL) Dim Container As BlobContainerClient = New BlobContainerClient(connectionString, containerDestName) Dim BlobClient As BlobClient = Container.GetBlobClient(Path.GetFileName(clientLocalFilePath)) ' 先检查Blob是否存在 If Not BlobClient.Exists() Then strReturn = "目标Blob不存在" Return Nothing End If Dim readOptions As BlobOpenReadOptions = New BlobOpenReadOptions(False) readOptions.Position = 0 textInStream = Await BlobClient.OpenReadAsync(readOptions) textIn = New StreamReader(textInStream) strReturn = "Success" Return textIn Catch er As Exception strReturn = String.Format("Failed to Stream from Storage Account: {0}-File:{1}-{2}", er.Message, Path.GetFileName(clientLocalFilePath), er.StackTrace) Return Nothing End Try End Function
4. 前置检查Blob存在性
在调用读取方法前,通过BlobClient.Exists()验证目标Blob是否存在,避免因Blob不存在触发的间接初始化异常。
内容的提问来源于stack exchange,提问作者user2413934

