【发布时间】:2020-12-15 11:21:07
【问题描述】:
我有一个 azure 函数(EventGrid 触发器),当在 blob 存储(Data Lake Storage Gen2)中创建新的 blob 时会触发该函数。 在这个函数中,我需要读取 blob 并将其反序列化为一个对象(类型已知)。
这是我用来获取 CloudBlob 的方法:
public async Task<CloudBlob> GetCloudBlob(Uri uri)
{
var cloudBlockBlob = new CloudBlob(uri, _storageCredentials);
if (await cloudBlockBlob.ExistsAsync())
return cloudBlockBlob;
return null;
}
通过这段代码,我读取了云 blob
using var stream = await cloudBlob.OpenReadAsync();
await _requestFileHandler.HandleFile(stream, name, prefix, cloudBlob.Uri);
在 HandleFile 方法中我调用了 DeserializeAsync 方法:
var model = await JsonSerializer.DeserializeAsync<RequestModel>(stream);
由于某种原因,流有时为空(stream.Length 为 0)导致此异常。
The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
有趣的是,如果我再次重试此 blob 的过程,则流会按预期填充。
我是否缺少任何等待条件,或者 Blob 仍未完全写入存储?
【问题讨论】:
-
将
await cloudBlockBlob.ExistsAsync()转换为await cloudBlockBlob.ExistsAsync().ConfigureAwait(false),await cloudBlob.OpenReadAsync()转换为await cloudBlob.OpenReadAsync().ConfigureAwait(false),await _requestFileHandler.HandleFile(stream, name, prefix, cloudBlob.Uri)转换为await _requestFileHandler.HandleFile(stream, name, prefix, cloudBlob.Uri).ConfigureAwait(false)和await JsonSerializer.DeserializeAsync<RequestModel>(stream)转换为await JsonSerializer.DeserializeAsync<RequestModel>(stream).ConfigureAwait(false)。它应该很可能工作。 -
@HarshitaSingh-MSFT 为什么要这么做?
-
你可以阅读这篇文章来深入了解-medium.com/bynder-tech/…
-
当应用
await关键字时,它会暂停调用方法并将控制权交还给调用者,直到等待的任务完成。我们可以避免强制延续/回调回到原始上下文,我们使用ConfigureAwait(false)来做到这一点。不使用ConfigureAwait(false)会导致性能问题和不可靠性。由于您没有使用它,stream有时在调用者上下文中,有时在当前上下文中。当前上下文中的一个为您提供正确的结果。您可以访问devblogs.microsoft.com/dotnet/configureawait-faq了解更多信息。 -
如果这回答了您的问题,请告诉我,我会将其作为答案发布。
标签: azure azure-functions azure-blob-storage azure-eventgrid azure-data-lake-gen2