【问题标题】:WebAPI return response conditionally and asyncWebAPI 有条件地和异步地返回响应
【发布时间】:2017-01-11 02:54:52
【问题描述】:

我有某种上传功能,它获取图像并将图像调整为不同大小,然后将 100x100 图像的路径返回给用户。 在我的情况下,用户将等到所有调整大小和上传完成,这显然不利于用户体验。 我尝试将我的 ActionResult 作为异步任务,但我无法做到。 这是我现在的代码,等待所有上传完成。

 [HttpPost]
    [Route("UploadProfileImage")]
    public async Task<IHttpActionResult> UploadProfileImage()
    {
        string userId= Identifier.GetIdentifier();
        ReturnResult response = new ReturnResult();
        try
        {

            var provider = new MultipartMemoryStreamProvider();
            await Request.Content.ReadAsMultipartAsync(provider);
            var fileNameParam = provider.Contents[0].Headers.ContentDisposition.Parameters.FirstOrDefault(p => p.Name.ToLower() == "filename");
            string fileName = (fileNameParam == null) ? "" : fileNameParam.Value.Trim('"');
            byte[] file = await provider.Contents[0].ReadAsByteArrayAsync();
            MemoryStream imgStream = new MemoryStream(file);
            Bitmap mg = new Bitmap(imgStream);
            List<Size> sizes = new List<Size>();
            sizes.Add(new Size { Width = mg.Width, Height = mg.Height });
            sizes.Add(new Size { Width = 100, Height = 100 });
            sizes.Add(new Size { Width = 300, Height = 300 });
            sizes.Add(new Size { Width = 500, Height = 500 });
            sizes.Add(new Size { Width = 800, Height = 800 });
            int index = 0;
            foreach (var size in sizes)
            {

                byte[] newImageByteArray = Helpers.CreateImageThumbnail(file, Convert.ToInt32(size.Width), Convert.ToInt32(size.Height));
                Helpers.SaveProfileImage(newImageByteArray, agentId, size, index == 0 ? true : false);
                index++;
               //---*--->>Here I Should check here that if original & 100x100 image were uploaded then return a response and continue uploading the others (if(index>1))
            }
            var path = "/users/uploads/100/" + userId+ ".jpg" + "?v=" + Guid.NewGuid();


            UserManager.UpdateUploadImage(userId, path);
            response.ReturnObject = path;
            response.ReturnCode = ReturnCodes.Success;
            return Ok(response);
        }
        catch (Exception ex)
        {
            response.ReturnObject = ex;
            response.ReturnCode = ReturnCodes.Exception;
            return Ok(response);
        }

注意:客户端是发布到 webapi 服务器的 angularJS 应用程序。 知道如何重写代码以实现这一目标吗?

【问题讨论】:

  • 旁注:我怀疑您的“用户”是客户端应用程序 - 在这种情况下,将服务器端代码从同步更改为异步将对客户端代码行为产生零影响,因为服务器调用无论如何都是异步的。请考虑您是否应该edit 发帖澄清这一点。
  • 用户是angularjs app
  • 我是这么认为的。单独重写服务器端代码并​​不能解决您的问题(通过并行化一些工作可能会减少等待时间,但不会完全删除它)。
  • 我明白了。但是,例如,如果我以某种方式将循环的其余部分发送到一个新线程,并返回当前线程,这还不足以解决问题吗?
  • 它是否能解决您的问题完全取决于您。请注意,您的建议通常是反对建议的做法,即不要将长时间运行的任务与 ASP.Net 中的请求分开......(除了因为您没有针对此类火灾的请求/响应/会话对象而充满意外- 并忘记任务)

标签: c# asynchronous asp.net-web-api async-await


【解决方案1】:

我尝试将我的 ActionResult 设为异步任务,但我无法做到。

这不是正确的解决方案,因为async doesn't change the HTTP protocol(正如我在博客中描述的那样)。因此,它不可能是正确的解决方案:

然后将 100x100 图像的路径返回给用户。

Web 请求如何向用户返回响应,然后再次返回(返回路径)?这对于 HTTP 之类的请求/响应协议是不可能的;每个请求只能得到一个响应。

在我的情况下,用户会等到所有调整大小和上传完成,这显然不利于用户体验。

您的选择是:

  1. 放入一个独立于 HTTP 请求来跟踪工作的复杂解决方案(这通常需要像 Azure 队列这样的可靠队列连接到像 Azure Function 这样的独立工作服务),然后提供一些方法来主动通知 UI完成(SignalR 对此很有用,除非您需要进行非常大的扩展,在这种情况下轮询实际上会更好)。
  2. 在客户端使用 AJAX。

请注意,您已经在执行 (2):

客户端是发布到 webapi 服务器的 angularJS 应用程序。

因此,您所要做的就是更改客户端,使其在允许用户执行其他操作之前不会等待请求。无需更改服务器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 2014-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多