Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用异步/等待时,流正在关闭_C#_Azure_Asynchronous_Asp.net Web Api - Fatal编程技术网

C# 使用异步/等待时,流正在关闭

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

我有一个将blob上传到Azure存储的小服务。我试图从WebApi异步操作中使用它,但我的
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);
}