2013-08-04 68 views
1

我有一個控制器如何從與ASP MVC 4異步控制器的EntityFramework 6數據的基礎數據異步從數據庫

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); 

當我試圖從da讀取數據時,我所做的是錯誤的方式ta基地在異步風格?

+0

有趣的是,這個問題多次出現在人們面前。至少每週10個問題。 – usr

回答

2

撥打Task的物業Result的呼叫是阻止呼叫,並且await的繼續將無法發佈到運行。

一旦你已經有一個任務返回方法,你爲什麼不使用await

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

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

有關該行的有趣的是,它調用SingleAsync,這是觀測一個TAP擴展方法。

我從來沒有使用暴露它的集合作爲observables的數據存儲庫,但我想它是可能。我的第一個猜測是[SingleAsync返回的任務沒有完成,因爲GoodImages可觀測值未完成。請注意0​​必須在它看到匹配後繼續掃描,以確保它與只匹配; FirstAsync更寬容,一旦看到第一場比賽就會完成。

在附註上,我建議使用await而不是Result,而不是在服務器上使用Task.Run。所以Paulo's answer在這方面是好的,雖然在這種情況下Result而不是造成死鎖。

+0

我相信EF 6通過擴展如SingleAsync支持異步。 – usr

+0

Single和First有不同的意圖,沒有一個比另一個更好或更有價值。根據你的意圖,你應該知道什麼時候使用一種或另一種。 (http://msmvps.com/blogs/paulomorgado/archive/2010/03/28/linq-single-vs-first.aspx)。 –