【问题标题】:Web API - An asynchronous module or handler completed while an asynchronous operation was still pendingWeb API - 异步模块或处理程序已完成,而异步操作仍处于挂起状态
【发布时间】:2014-10-01 21:48:04
【问题描述】:

想不出来这个。想法?

[控制器]

await _imageRepo.Resize(name, width, height, queryParams, (image) =>
{
    response = createResponse(image);
});

[存储库]

public async Task Resize(string name, string width, string height, ImageOptions options, Action<Images> callback)
{
    var actionName = "resized";
    var newWidth = Convert.ToInt32(width);
    var newHeight = string.IsNullOrEmpty(height) ? newWidth : Convert.ToInt32(height);
    var resizedName = ApplyOptionName(string.Format("{0}-{3}-{1}x{2}", name, newWidth, newHeight, actionName), options);

    await Get(resizedName, null, async (previousImage) =>
    {
        if (previousImage != null)
        {
            callback(previousImage);
            return;
        }

        await Get(name, null, image =>
        {
            if (image == null)
            {
                callback(null);
                return;
            }

            using (ImageFactory imageFactory = new ImageFactory())
            {
                imageFactory.Load(image.ToStream());

                imageFactory.Resize(new ResizeLayer(new Size(newWidth, newHeight), ResizeMode.Max, AnchorPosition.Left));

                ProcessImageOptions(imageFactory, options);

                using (MemoryStream ms = new MemoryStream())
                {
                    imageFactory.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

                    var newImage = Create(new Images(ms) { Name = resizedName });

                    callback(newImage);
                }
            }

        });

    });

}

[例外]

[InvalidOperationException: An asynchronous module or handler completed while an asynchronous operation was still pending.]

所有这些回调都不在我的胃里,但为什么我会收到这个错误?

【问题讨论】:

  • 我会让你的仓库返回图片,然后构建响应。 (去掉回调参数)
  • 我怀疑Get 的回调是Action,这将强制async lambda 为async void,从而导致此问题。最好的解决方案是完全摆脱 IMO 的回调,但您也可以将它们更改为 Func&lt;..., Task&gt;await 它们。

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


【解决方案1】:

虽然回调不是很好。我们决定继续使用这种模式。这意味着要弄清楚如何使那些 lambda 的返回任务。

这很容易。

正如 Stephen Cleary 所写的“将它们更改为 Func<... task>...”。

所以这是最终的实现。

public async Task Resize(string name, string width, string height, ImageOptions options, Func<Images, Task> callback)
{
    var actionName = "resized";
    var newWidth = Convert.ToInt32(width);
    var newHeight = string.IsNullOrEmpty(height) ? newWidth : Convert.ToInt32(height);
    var resizedName = ApplyOptionName(string.Format("{0}-{3}-{1}x{2}", name, newWidth, newHeight, actionName), options);

    await Get(resizedName, null, async (previousImage) =>
    {
        Images resizedImage = null;

        if (previousImage != null)
        {
            resizedImage = previousImage;
        }
        else
        {
            await Get(name, null, async (image) =>
            {
                if (image == null)
                {
                    resizedImage = null;
                    return;
                }

                using (ImageFactory imageFactory = new ImageFactory())
                {
                    imageFactory.Load(image.ToStream());

                    imageFactory.Resize(new ResizeLayer(new Size(newWidth, newHeight), ResizeMode.Max, AnchorPosition.Left));

                    ProcessImageOptions(imageFactory, options);

                    using (MemoryStream ms = new MemoryStream())
                    {
                        imageFactory.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

                        resizedImage = await CreateAsync(new Images(ms) { Name = resizedName });
                    }
                }

            });
        }

        await callback(resizedImage);

    });

}

一个小的重构......但没有造成任何伤害。

感谢您的帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 2013-03-08
    • 1970-01-01
    相关资源
    最近更新 更多