เมื่อใดก็ตามที่คุณต้องดำเนินการกับเซิร์ฟเวอร์ระยะไกลโปรแกรมของคุณจะสร้างคำขอส่งไปแล้วรอการตอบกลับ ฉันจะใช้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คุณควรจะเพิ่มประสิทธิภาพของแอปพลิเคชันของคุณอย่างมาก