如何使用asp mvc 4异步控制器从数据库获取数据,并从数据库中读取EntityFramework 6 async

时间:2013-08-04 18:27:52

标签: asp.net-mvc entity-framework async-await c#-5.0

我有下一个控制器

public async Task<ActionResult> ImageAsync(int id)
{
    var img = await _repository.GetImageAsync(id);
    if (img != null)
    {
        return File(img, "image/jpg"); //View(img);
    }
    byte[] res = new byte[0];
    return File(res, "image/jpg");
}

和存储库中的方法

public async Task<byte[]> GetImage(int imageId)
{
    try
    {
        var dbCtx = new smartbags_storeEntities();

        var res = await dbCtx.GoodImages.SingleAsync(d => d.ImageId == imageId);
        return res != null ? res.ImageData : null;
    }
    catch (Exception ex)
    {

        throw ex;
    }
}

public async Task<byte[]> GetImageAsync(int imageId)
{
    byte[] img = await Task.Run(() =>
    {
        var res = GetImage(imageId).Result;
        if (res != null)
        {
            var wi = new System.Web.Helpers.WebImage(res);

            wi.AddTextWatermark("info");

            return wi.GetBytes();
        }
        return null;
    });

    return img;
}

但图像阅读的执行在线冻结

var res = await dbCtx.GoodImages.SingleAsync(d => d.ImageId == imageId);

当我尝试以异步样式从数据库中读取数据时,我做错了什么?

2 个答案:

答案 0 :(得分:2)

Result的{​​{1}}媒体资源的调用是阻止调用,Task的延续将无法发布以进行运行。

一旦你有一个任务返回方法,你为什么不只使用await

await

答案 1 :(得分:2)

关于该行的有趣之处在于它调用SingleAsync,这是 observables 的TAP扩展方法。

我从未使用过将其集合公开为可观察对象的数据存储库,但我认为它是可能的。我的第一个猜测是[{1}}返回的任务没有完成,因为SingleAsync observable没有完成。请注意GoodImages必须在看到匹配后继续扫描,以确保它是匹配; SingleAsync更宽容,并会在看到第一场比赛后立即完成。

另外,我建议使用FirstAsync代替await而不是在服务器上使用Result。因此Paulo's answer在这方面表现不错,但在这种情况下,Task.Run 导致死锁。