从 WEB API 控制器以异步方法返回 Void

Posted

技术标签:

【中文标题】从 WEB API 控制器以异步方法返回 Void【英文标题】:Returning Void in Async method from WEB API Controller 【发布时间】:2012-08-08 13:13:32 【问题描述】:

我在 ASP.NET MVC 4 WEB API 控制器中有这个异步方法,我从这个博客得到: http://www.strathweb.com/2012/04/html5-drag-and-drop-asynchronous-multi-file-upload-with-asp-net-webapi/

  public async Task<IList<RecivedFile>> Post()
    
        List<RecivedFile> result = new List<RecivedFile>();
        if (Request.Content.IsMimeMultipartContent())
        
            try
            
                MultipartFormDataStreamProvider stream = new MultipartFormDataStreamProvider(HostingEnvironment.MapPath("~/USER-UPLOADS"));

                IEnumerable<HttpContent> bodyparts = await Request.Content.ReadAsMultipartAsync(stream);
                IDictionary<string, string> bodyPartFiles = stream.BodyPartFileNames;
                IList<string> newFiles = new List<string>();

                foreach (var item in bodyPartFiles)
                
                    var newName = string.Empty;
                    var file = new FileInfo(item.Value);

                    if (item.Key.Contains("\""))
                        newName = Path.Combine(file.Directory.ToString(), item.Key.Substring(1, item.Key.Length - 2));
                    else
                        newName = Path.Combine(file.Directory.ToString(), item.Key);

                    File.Move(file.FullName, newName);
                    newFiles.Add(newName);
                

                var uploadedFiles = newFiles.Select(i =>
                
                    var fi = new FileInfo(i);
                    return new RecivedFile(fi.Name, fi.FullName, fi.Length);
                ).ToList();

                result.AddRange(uploadedFiles);
            
            catch (Exception e)
            
            
        
        return result;
    

我的问题是为什么这个方法的返回类型是 Task?尚不清楚它返回此任务的“去哪里”或“给谁”?就像没有人等待/接收返回的对象一样。

我想知道如果我这样返回 void 会有什么影响:

编辑:

我已经尝试了下面的代码,它完全破坏了程序。就像运行时失去了对代码的引用,代码本身并没有完成运行。

    public async void Post()
    
        List<RecivedFile> result = new List<RecivedFile>();
        if (Request.Content.IsMimeMultipartContent())
        
            try
            
                MultipartFormDataStreamProvider stream = new MultipartFormDataStreamProvider(HostingEnvironment.MapPath("~/USER-UPLOADS"));

                IEnumerable<HttpContent> bodyparts = await Request.Content.ReadAsMultipartAsync(stream);
                IDictionary<string, string> bodyPartFiles = stream.BodyPartFileNames;
                IList<string> newFiles = new List<string>();

                foreach (var item in bodyPartFiles)
                
                    var newName = string.Empty;
                    var file = new FileInfo(item.Value);

                    if (item.Key.Contains("\""))
                        newName = Path.Combine(file.Directory.ToString(), item.Key.Substring(1, item.Key.Length - 2));
                    else
                        newName = Path.Combine(file.Directory.ToString(), item.Key);

                    File.Move(file.FullName, newName);
                    newFiles.Add(newName);
                

            
            catch (Exception e)
            
            
        

    

【问题讨论】:

【参考方案1】:

ASP.NET 运行时等待它。您可能会发现this video 很有用。

async 的大多数示例都假设一个 UI 上下文。 ASP.NET also provides a context,但它是一个“请求”上下文 - 每个 HTTP 请求一个。我的async/await post 概述了这个“上下文”,async/await FAQ 更详细。

【讨论】:

所以结论是在 ASP.NET 中使用时永远不要在异步方法中返回 void 在 ASP.NET 4.5 中有少数情况可以使用 async void 方法 - 运行时会检测到它并做出适当的反应。但作为一般规则,最好使用async Task,除非你真的不得不async void 因为 async void 本质上是“一劳永逸”,很少有理由这样做。一个例子是新 Web 表单中的 page_load - protected async void Page_Load(object sender, EventArgs e)【参考方案2】:

使用返回类型 void,您无需等待对象返回。您等待操作完成。您等待您的任务完成。

【讨论】:

不确定你说“你”(“你不等”)指的是谁。我不想等待任何事情。这里的要点是它用于WEB API,我不明白你到底想让我等什么?【参考方案3】:

如果您返回 void,无论您的异步操作的完成状态如何,您都将立即返回 204“No Content”响应消息。这是在VoidResultConverter 的帮助下完成的。

注意:在 RC 上,您会看到它返回 200 “OK”响应,但带有 RTM,它将返回 204 "No Content" 响应。

【讨论】:

以上是关于从 WEB API 控制器以异步方法返回 Void的主要内容,如果未能解决你的问题,请参考以下文章

C#.NET Web API 2,如何使用 HTTPGET 异步方法上的 HttpContent 从网站中提取特定文本?

从同步控制器方法到异步控制器方法的正确转换(使用void时)

Web API 方法的返回类型格式器过滤器

从 Web Api 控制器返回 http 状态码

如何使 ASP.NET Core Web API 操作异步执行?

从 Web API 同步调用外部 api