リモートサーバーでアクションを実行する必要があるときはいつでも、プログラムは要求を生成して送信し、応答を待ちます。私が使用するSaveChanges()
と、SaveChangesAsync()
一例としてではなく、同じことがに適用Find()
してFindAsync()
。
myList
データベースに追加する必要がある100以上のアイテムのリストがあるとします。これを挿入すると、関数は次のようになります。
using(var context = new MyEDM())
{
context.MyTable.AddRange(myList);
context.SaveChanges();
}
最初にのインスタンスを作成しMyEDM
、リストmyList
をテーブルに追加してからMyTable
、を呼び出しSaveChanges()
てデータベースへの変更を永続化します。それはあなたが望むように機能し、レコードはコミットされますが、プログラムはコミットが完了するまで他に何もできません。何をコミットしているかによっては、これには長い時間がかかる場合があります。レコードへの変更をコミットする場合、エンティティは一度に1つずつコミットする必要があります(私はかつて、更新に2分かかる保存がありました)。
この問題を解決するには、次の2つのいずれかを実行できます。1つ目は、挿入を処理するために新しいスレッドを開始できることです。これにより、呼び出し元のスレッドが解放されて実行を続行できますが、そこに座って待機する新しいスレッドを作成しました。そのオーバーヘッドは必要ありませんasync await
。これがパターンが解決するものです。
I / O操作の場合、await
すぐに親友になります。上記のコードセクションを使用して、次のように変更できます。
using(var context = new MyEDM())
{
Console.WriteLine("Save Starting");
context.MyTable.AddRange(myList);
await context.SaveChangesAsync();
Console.WriteLine("Save Complete");
}
これは非常に小さな変更ですが、コードの効率とパフォーマンスに大きな影響があります。では、どうなるのでしょうか。コードの初めは、あなたがのインスタンスを作成し、同じであるMyEDM
と、あなたの追加myList
にはMyTable
。しかし、を呼び出すとawait context.SaveChangesAsync()
、コードの実行は呼び出し元の関数に戻ります。したがって、これらすべてのレコードがコミットされるのを待っている間、コードは実行を継続できます。上記のコードを含む関数のシグネチャがpublic async Task SaveRecords(List<MyTable> saveList)
であるとすると、呼び出し元の関数は次のようになります。
public async Task MyCallingFunction()
{
Console.WriteLine("Function Starting");
Task saveTask = SaveRecords(GenerateNewRecords());
for(int i = 0; i < 1000; i++){
Console.WriteLine("Continuing to execute!");
}
await saveTask;
Console.Log("Function Complete");
}
なぜこのような機能があるのかはわかりませんが、出力される内容はどのようにasync await
機能するかを示しています。まず、何が起こるかを見てみましょう。
実行が入りMyCallingFunction
、Function Starting
その後、Save Starting
その関数は、コンソールに書き込まれますSaveChangesAsync()
呼び出されます。この時点で、実行はMyCallingFunction
forループに戻り、最大1000回まで「実行を継続」と書き込みます。ときSaveChangesAsync()
に終了し、実行が戻るSaveRecords
の書き込み機能、Save Complete
コンソールに。すべてがSaveRecords
完了すると、実行は終了MyCallingFunction
時の状態SaveChangesAsync()
で続行されます。混乱していますか?出力例を次に示します。
機能開始
保存開始
実行を続けます!
実行を続けます!
実行を続けます!
実行を続けます!
実行を続けます!
...。
実行を続けます!
保存完了!
実行を続けます!
実行を続けます!
実行を続けます!
...。
実行を続けます!
機能完了!
または多分:
機能開始
保存開始
実行を続けます!
実行を続けます!
保存完了!
実行を続けます!
実行を続けます!
実行を続けます!
...。
実行を続けます!
機能完了!
それがの美しさですasync await
。何かが終了するのを待っている間、コードを実行し続けることができます。実際には、呼び出し関数として次のような関数があります。
public async Task MyCallingFunction()
{
List<Task> myTasks = new List<Task>();
myTasks.Add(SaveRecords(GenerateNewRecords()));
myTasks.Add(SaveRecords2(GenerateNewRecords2()));
myTasks.Add(SaveRecords3(GenerateNewRecords3()));
myTasks.Add(SaveRecords4(GenerateNewRecords4()));
await Task.WhenAll(myTasks.ToArray());
}
ここでは、4つの異なる保存レコード機能が同時に実行されています。個々の関数が連続して呼び出された場合よりも、MyCallingFunction
を使用するとはるかに速く完了します。async await
SaveRecords
まだ触れていないのはawait
キーワードです。これは、Task
待っていることが完了するまで、現在の関数の実行を停止します。したがって、オリジナルの場合、関数が終了するまでそのMyCallingFunction
行Function Complete
はコンソールに書き込まれませんSaveRecords
。
簡単に言うと、使用するオプションがある場合async await
は、アプリケーションのパフォーマンスが大幅に向上するため、使用する必要があります。