2012-11-12 29 views
5

我在EF6中看到了一個新特性,即異步方法。我找到一個例子。EF中這兩個異步調用有什麼區別?

這第一條路是正常通話,與EF5例如:

public Store FindClosestStore(DbGeography location) 
{ 
    using (var context = new StoreContext()) 
    { 
     return (from s in context.Stores 
      orderby s.Location.Distance(location) 
      select s).First(); 
    } 
} 

而新的呼叫,在EF6異步方法。

public async Task<Store> FindClosestStore(DbGeography location) 
{ 
    using (var context = new StoreContext()) 
    { 
     return await (from s in context.Stores 
      orderby s.Location.Distance(location) 
      select s).FirstAsync(); 
    } 
} 

不過,我可以做以下(在大成是aprox的,我這樣做是由內存):

public async Task<Store> MyAsyncMethod(DbGeography location) 
{ 
    return await Task.Run(() => FindClosestStore()); 
} 

我的意思是,我可以使用Task.Run調用第一種方法,那就是沒有異步,等待結果。目前,我用來調用異步的方法,不僅是EF。這也是一個異步調用,或者當我使用EF6異步方法時,真正的異步調用是什麼?

爲什麼在新版本的EF6中需要異步方法?只是爲了簡單?

+0

async和await是語法糖,新的.Net 4.5,你可以通過任務與ContinueWith –

回答

9

這裏的區別在於代碼是如何等待的。

在此代碼:

public async Task<Store> FindClosestStore(DbGeography location) 
{ 
    using (var context = new StoreContext()) 
    { 
     return await (from s in context.Stores 
      orderby s.Location.Distance(location) 
      select s).FirstAsync(); 
    } 
} 

EF會發出對數據庫的查詢,並返回。

一旦結果返回,任務將完成,await塊將繼續執行。

也就是說,.NET本身沒有線程正在等待響應。 有(希望)來自數據庫驅動程序的較低級別的回調,當結果到達時通知.NET。

(這是至少IO如何等異步工作在.NET和我承擔ADO.NET異步相同)

在另一種情況:

public async Task<Store> MyAsyncMethod(DbGeography location) 
{ 
    return await Task.Run(()=> FindClosestStore()); 
} 

會有一個線程等待數據庫的響應。也就是說,你將會阻塞IO,但是它會被你的task.run技巧隱藏起來。

這兩種情況對消費者來說都是一樣的,區別在於你在上一個例子中佔用了資源。

+0

我認爲async/await的使用避免了使用新線程的需要。有時是創造的,有時不是(取決於追求)。事實上,在WCF中,它使用異步/等待模式在請求被服務時釋放資源。對於EF,它會以相同的方式工作,在請求正在執行時釋放資源? –

+2

在最後一個代碼示例中,會有一個阻塞線程,因爲它使用非異步EF方法。即使您將該調用包裝在異步/等待塊中。那是。 「FindClosestStore()」會阻止幕後的線程 –

+0

,這在使用異步/等待時不會發生在WCF中?有什麼方法可以使用EF5的異步? –