5

EF6の新機能である非同期メソッドを見てきました。例を見つけます。

この最初の方法は通常の呼び出しであり、たとえば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();
    }
}

しかし、私は次のことを行うことができます(構文は約です、私はメモリによってそれを行います):

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

つまり、Task.Runを使用して、非同期ではない最初のメソッドを呼び出して、結果を待つことができます。現時点では、EFだけでなく、任意のメソッドを非同期に呼び出すために使用する方法です。これも非同期呼び出しですか、それともEF6非同期メソッドを使用する場合の真の非同期呼び出しですか?

新しいバージョンのEF6で非同期メソッドが必要なのはなぜですか?簡単にするためだけですか?

4

1 に答える 1

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に通知するdbドライバーからの低レベルのコールバックが(うまくいけば)あります。

(これは、少なくとも他の非同期IOが.NETでどのように機能するかであり、ADO.NET非同期でも同じであると想定しています)

その他の場合:

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

DBからの応答を待機しているスレッドがあります。つまり、ブロッキングIOがありますが、task.runトリックでコンシューマーから隠されます。

どちらの場合も、コンシューマーに対して同じように動作します。違いは、最後の例でリソースを占有していることです。

于 2012-11-12T10:39:42.973 に答える