Uzak bir sunucuda herhangi bir işlem yapmanız gerektiğinde, programınız isteği oluşturur, gönderir ve ardından bir yanıt bekler. Örnek olarak SaveChanges()ve kullanacağım SaveChangesAsync()ama aynısı Find()ve için de geçerli FindAsync().
myListVeritabanınıza eklemeniz gereken 100'den fazla öğe listeniz olduğunu varsayalım. Bunu eklemek için, işleviniz şuna benzer:
using(var context = new MyEDM())
{
context.MyTable.AddRange(myList);
context.SaveChanges();
}
Önce bir örneğini oluşturursunuz MyEDM, listeyi myListtabloya eklersiniz MyTable, ardından SaveChanges()değişiklikleri veritabanında sürdürmek için çağırırsınız . İstediğiniz gibi çalışır, kayıtlar işlenir, ancak programınız kesinleştirme bitene kadar başka bir şey yapamaz. Bu, ne taahhüt ettiğinize bağlı olarak uzun zaman alabilir. Kayıtlarda değişiklik yapıyorsanız, kuruluş bunları teker teker işlemelidir (bir kez kaydetmiştim, güncellemeler için 2 dakika ayırın)!
Bu sorunu çözmek için iki şeyden birini yapabilirsiniz. İlki, eki işlemek için yeni bir diş açabilirsiniz. Bu, çalıştırmaya devam etmek için çağıran iş parçacığını serbest bırakacak olsa da, orada oturup bekleyecek yeni bir iş parçacığı oluşturdunuz. Bu ek yüke gerek yoktur ve async awaitmodelin çözdüğü şey budur .
I / O işlemleri için, awaitçabucak en iyi arkadaşınız olur. Kod bölümünü yukarıdan alarak, şu şekilde değiştirebiliriz:
using(var context = new MyEDM())
{
Console.WriteLine("Save Starting");
context.MyTable.AddRange(myList);
await context.SaveChangesAsync();
Console.WriteLine("Save Complete");
}
Bu çok küçük bir değişikliktir, ancak kodunuzun verimliliği ve performansı üzerinde derin etkileri vardır. Peki ne olur? Kodun başlangıcı size bir örneğini oluşturmak, aynı MyEDMve eklemek myListTo MyTable. Ancak aradığınızda await context.SaveChangesAsync(), kodun yürütülmesi çağıran işleve geri döner! Böylece, tüm bu kayıtların işlenmesini beklerken, kodunuz çalışmaya devam edebilir. Yukarıdaki kodu içeren işlevin imzasına sahip olduğunu public async Task SaveRecords(List<MyTable> saveList)varsayalım, çağıran işlev şöyle görünebilir:
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");
}
Neden böyle bir işleve sahip olurdunuz bilmiyorum ama çıkardığı şey nasıl async awaitçalıştığını gösteriyor . İlk önce ne olduğunu gözden geçirelim.
Yürütme girer MyCallingFunction, Function Startingardından Save Startingkonsola yazılır, ardından işlev SaveChangesAsync()çağrılır. Bu noktada, yürütme MyCallingFunction1000 defaya kadar 'Yürütmeye Devam Ediyor' yazan for döngüsüne döner ve girer. Bittiğinde SaveChangesAsync(), yürütme konsola SaveRecordsyazarak işleve döner Save Complete. Her şey SaveRecordstamamlandığında, yürütme tamamlandığında MyCallingFunctionolduğu gibi devam edecek SaveChangesAsync(). Şaşkın? İşte bir örnek çıktı:
İşlev Başlangıcı
Başlangıcı Kaydet
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
....
Yürütmeye devam ediyor!
Kaydetme Tamamlandı!
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
....
Yürütmeye devam ediyor!
İşlev Tamamlandı!
Ya da belki:
İşlev Başlangıcı
Başlangıcı Kaydet
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
Kaydetme Tamamlandı!
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
Yürütmeye devam ediyor!
....
Yürütmeye devam ediyor!
İşlev Tamamlandı!
İşin güzelliği bu async await, bir şeyin bitmesini beklerken kodunuz çalışmaya devam edebilir. Gerçekte, arama işleviniz olarak şuna benzer bir işleve sahip olursunuz:
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());
}
Burada, aynı anda giden dört farklı kaydetme kayıt fonksiyonuna sahipsiniz . işlevlerin seri olarak çağrılmasına göre MyCallingFunctionçok daha hızlı tamamlanır .async awaitSaveRecords
Henüz değinmediğim tek şey awaitanahtar kelime. Bunun yaptığı şey Task, beklediğiniz şey tamamlanana kadar mevcut işlevin yürütülmesini durdurmaktır . Yani orijinal durumunda , fonksiyon bitene kadar MyCallingFunctionsatır Function Completekonsola yazılmayacaktır SaveRecords.
Uzun lafın kısası, kullanma seçeneğiniz varsa async await, uygulamanızın performansını büyük ölçüde artıracağı için yapmalısınız.