เมื่อใดก็ตามที่คุณต้องดำเนินการกับเซิร์ฟเวอร์ระยะไกลโปรแกรมของคุณจะสร้างคำขอส่งไปแล้วรอการตอบกลับ ฉันจะใช้SaveChanges()
และSaveChangesAsync()
เป็นตัวอย่าง แต่เช่นเดียวกับFind()
และFindAsync()
และ
สมมติว่าคุณมีรายการmyList
มากกว่า 100 รายการที่คุณต้องเพิ่มในฐานข้อมูลของคุณ ในการแทรกฟังก์ชันของคุณจะมีลักษณะดังนี้:
using(var context = new MyEDM())
{
context.MyTable.AddRange(myList);
context.SaveChanges();
}
ขั้นแรกให้คุณสร้างอินสแตนซ์MyEDM
เพิ่มรายการmyList
ลงในตารางMyTable
จากนั้นเรียกSaveChanges()
เพื่อคงการเปลี่ยนแปลงในฐานข้อมูล มันทำงานตามที่คุณต้องการบันทึกจะได้รับความมุ่งมั่น แต่โปรแกรมของคุณไม่สามารถทำอย่างอื่นได้จนกว่าการคอมมิตจะเสร็จสิ้น การดำเนินการนี้อาจใช้เวลานานขึ้นอยู่กับสิ่งที่คุณกำลังกระทำ หากคุณกำลังดำเนินการเปลี่ยนแปลงระเบียนเอนทิตีจะต้องดำเนินการทีละรายการ (ครั้งหนึ่งฉันใช้เวลาบันทึก 2 นาทีในการอัปเดต)!
ในการแก้ปัญหานี้คุณสามารถทำอย่างใดอย่างหนึ่งจากสองสิ่ง อย่างแรกคือคุณสามารถเริ่มเธรดใหม่เพื่อจัดการกับส่วนแทรก ในขณะนี้จะทำให้เธรดการโทรฟรีเพื่อดำเนินการต่อ แต่คุณได้สร้างเธรดใหม่ที่จะนั่งรอ ไม่จำเป็นต้องมีค่าใช้จ่ายนั้นและนี่คือสิ่งที่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
และเข้าสู่การเขียนสำหรับลูป 'ดำเนินการต่อเพื่อดำเนินการ' สูงสุด 1,000 ครั้ง เมื่อ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());
}
ที่นี่คุณมีสี่ที่แตกต่างกันประหยัดฟังก์ชั่นการบันทึกไปในเวลาเดียวกัน MyCallingFunction
จะทำงานได้เร็วขึ้นมากโดยใช้async await
มากกว่ากรณีที่SaveRecords
เรียกใช้ฟังก์ชันแต่ละชุดเป็นชุด
สิ่งหนึ่งที่ฉันยังไม่ได้สัมผัสคือawait
คีย์เวิร์ด สิ่งนี้จะหยุดไม่ให้ฟังก์ชันปัจจุบันทำงานจนกว่าสิ่งที่Task
คุณรอคอยจะเสร็จสมบูรณ์ ดังนั้นในกรณีของต้นฉบับMyCallingFunction
บรรทัดFunction Complete
จะไม่ถูกเขียนลงในคอนโซลจนกว่าSaveRecords
ฟังก์ชันจะเสร็จสิ้น
เรื่องสั้นขนาดยาวหากคุณมีตัวเลือกในการใช้งานasync await
คุณควรจะเพิ่มประสิทธิภาพของแอปพลิเคชันของคุณอย่างมาก