C# 使用异步/等待时,流正在关闭
我有一个将blob上传到Azure存储的小服务。我试图从WebApi异步操作中使用它,但我的C# 使用异步/等待时,流正在关闭,c#,azure,asynchronous,asp.net-web-api,C#,Azure,Asynchronous,Asp.net Web Api,我有一个将blob上传到Azure存储的小服务。我试图从WebApi异步操作中使用它,但我的AzureFileStorageService表示流已关闭 我不熟悉async/await,有什么好的资源可以帮助我更好地理解它吗 WebApi控制器 public class ImageController : ApiController { private IFileStorageService fileStorageService; public ImageController(I
AzureFileStorageService
表示流已关闭
我不熟悉async/await,有什么好的资源可以帮助我更好地理解它吗
WebApi控制器
public class ImageController : ApiController
{
private IFileStorageService fileStorageService;
public ImageController(IFileStorageService fileStorageService)
{
this.fileStorageService = fileStorageService;
}
public async Task<IHttpActionResult> Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType));
}
await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider()).ContinueWith((task) =>
{
foreach (var item in task.Result.Contents)
{
using (var fileStream = item.ReadAsStreamAsync().Result)
{
fileStorageService.Save(@"large/Sam.jpg", fileStream);
}
item.Dispose();
}
});
return Ok();
}
}
Save()方法有问题:您没有返回任务,因此调用方法无法等待任务完成。如果您只是想触发并忘记它,那么这很好,但您不能这样做,因为您传入的流将在
Save()
方法返回时立即被处理(这要感谢using
语句)
相反,您必须在调用方法中返回任务
和等待
,或者您必须在使用
块中不包含文件流,而是让Save()
方法在完成后处理它
重新编写代码的一种方法如下:
(调用方法的片段):
以及保存方法:
public async Task Save(string path, Stream source)
{
await CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"])
.CreateCloudBlobClient()
.GetContainerReference("images")
.GetBlockBlobReference(path)
.UploadFromStreamAsync(source);
}
检查我们几周前刚刚发布的AzureBlobUpload样本: 前面的答案肯定是一个很好的解决方案。这只是一个完整的端到端的官方示例(可能供其他人开始使用)
项目.处置()代码>是冗余的<当项使用
块离开的作用域时,已对其调用了code>Dispose()
。实际上,这可能就是问题所在。一切都是通过async
和wait
设置的;在检索结果之前,using
块可能会过早地关闭流。@RobertHarvey-So项。调用结果上的Dispose()
,以及结果上的Dispose()
,在本例中是流
?您的保存()有问题
method:您没有返回任务,因此调用方法无法等待任务完成。因此,在调用它之后,您立即离开using
块,流被释放,很可能是在保存完成项之前。Dispose()
很好:using
语句正在处理流,而不是项。另外,ContinueWith
可以替换为wait
。谢谢!你有什么好的网站推荐,可以简单明了地解释wait/async吗?@stephenleary-wait
哪里可以被替换?@Sam MSDN文档是一个不错的起点,Stephen Toub和Eric Lippert各自的博客文章集也是很好的、可访问的资源。坦率地说,斯蒂芬·克利里(Stephen Cleary)也有一个不错的系列:)@Sam在等待结果之前,您的代码当前在任务中使用ContinueWith
。但是await
本质上是一种绕过ContinueWith
的方法:只需await
原始任务,然后方法的其余部分自动成为ContinueWith。因此,实际上您可以通过
删除continue。
var result = await Request.Content.ReadAsMultipartAsync(new MultipartMemoryStreamProvider());
foreach (var item in result.Contents)
{
using (var fileStream = await item.ReadAsStreamAsync())
{
await fileStorageService.Save(@"large/Sam.jpg", fileStream);
}
item.Dispose();
}
public async Task Save(string path, Stream source)
{
await CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"])
.CreateCloudBlobClient()
.GetContainerReference("images")
.GetBlockBlobReference(path)
.UploadFromStreamAsync(source);
}