มันเป็นลูกผสมหรือเปล่า (เช่นโปรแกรม. NET ของฉันจะใช้สแต็กจนกว่าจะถึงการเรียกใช้ async จากนั้นสลับไปยังโครงสร้างอื่น ๆ จนกว่าจะเสร็จสมบูรณ์ ณ จุดที่สแต็กนั้นกลับมาอยู่ในสถานะที่สามารถมั่นใจได้ในรายการถัดไป ฯลฯ )
ใช่แล้ว
สมมติว่าเรามี
async void MyButton_OnClick() { await Foo(); Bar(); }
async Task Foo() { await Task.Delay(123); Blah(); }
ต่อไปนี้เป็นคำอธิบายที่ง่ายมากของวิธีการแก้ไขต่อเนื่อง รหัสจริงมีความซับซ้อนมากกว่านี้มาก
คุณคลิกที่ปุ่ม ข้อความถูกจัดคิว วนรอบข้อความประมวลผลข้อความและเรียกใช้ตัวจัดการการคลิกวางที่อยู่ผู้ส่งของคิวข้อความบนสแต็ก นั่นคือสิ่งที่เกิดขึ้นหลังจากดำเนินการจัดการคือการวนรอบข้อความจะต้องทำงานต่อไป ดังนั้นความต่อเนื่องของตัวจัดการคือการวนซ้ำ
ตัวจัดการการคลิกเรียก Foo () โดยวางที่อยู่ผู้ส่งของตัวเองไว้บนสแต็ก นั่นคือความต่อเนื่องของ Foo คือส่วนที่เหลือของตัวจัดการการคลิก
Foo เรียกใช้ Task.Delay วางที่อยู่ผู้ส่งคืนลงในสแต็ก
Task.Delay ทำสิ่งที่ต้องใช้เวทมนตร์เพื่อส่งคืนภารกิจทันที สแต็กถูกตอกและเรากลับมาที่ฟู
ฟูตรวจสอบภารกิจที่ส่งคืนเพื่อดูว่างานเสร็จสมบูรณ์หรือไม่ มันไม่ใช่. ความต่อเนื่องของการรอคอยคือการเรียก Blah () ดังนั้น Foo จึงสร้างผู้รับมอบสิทธิ์ซึ่งเรียก Blah () และแสดงให้เห็นว่าผู้ได้รับมอบหมายเป็นความต่อเนื่องของงาน (ฉันเพิ่งทำผิดพลาดเล็กน้อยคุณจับมันได้หรือไม่ถ้าไม่เราจะเปิดเผยในอีกสักครู่)
จากนั้นฟูสร้างวัตถุงานของตัวเองทำเครื่องหมายว่าไม่สมบูรณ์และส่งคืนสแต็กไปยังตัวจัดการการคลิก
ตัวจัดการการคลิกตรวจสอบงานของ Foo และค้นพบว่างานไม่สมบูรณ์ ความต่อเนื่องของการรอคอยในตัวจัดการคือการเรียก Bar () ดังนั้นตัวจัดการการคลิกจะสร้างผู้รับมอบสิทธิ์ซึ่งเรียก Bar () และตั้งเป็นความต่อเนื่องของงานที่ส่งคืนโดย Foo () จากนั้นส่งคืนสแต็กไปยังลูปข้อความ
วนรอบข้อความยังคงประมวลผลข้อความ ในที่สุดเวทย์มนตร์ตัวจับเวลาที่สร้างโดยงานการหน่วงเวลาจะทำสิ่งนั้นและโพสต์ข้อความไปยังคิวโดยบอกว่าตอนนี้สามารถดำเนินการต่อเนื่องของงานการหน่วงเวลาได้ ดังนั้นการวนรอบข้อความจึงเรียกความต่อเนื่องของงานวางตัวเองบนสแต็กตามปกติ ผู้รับมอบสิทธิ์นั้นเรียกว่า Blah () Blah () ทำในสิ่งที่มันทำและคืนค่าสแต็ก
เกิดอะไรขึ้น นี่คือบิตหากิน ความต่อเนื่องของงานล่าช้าไม่เพียง แต่เรียก Blah () มันต้องเรียกการโทรไปที่ Bar ()แต่ภารกิจนั้นไม่รู้เกี่ยวกับ Bar!
Foo จริงสร้างตัวแทนว่า (1) เรียก Blah () และ (2) เรียกความต่อเนื่องของงานที่สร้างขึ้นฟูและกลับมามอบให้จัดการเหตุการณ์ นั่นคือวิธีที่เราเรียกผู้ได้รับมอบหมายที่เรียก Bar ()
และตอนนี้เราได้ทำทุกสิ่งที่เราต้องทำตามลำดับที่ถูกต้อง แต่เราไม่เคยหยุดการประมวลผลข้อความในการวนรอบข้อความนานมากดังนั้นแอปพลิเคชันยังคงตอบสนอง
ว่าสถานการณ์เหล่านี้สูงเกินไปสำหรับสแต็กทำให้รู้สึกที่สมบูรณ์แบบ แต่สิ่งที่แทนที่สแต็ค?
กราฟของวัตถุภารกิจที่มีการอ้างอิงถึงกันและกันผ่านคลาสปิดของผู้ได้รับมอบหมาย ชั้นเรียนปิดเป็นเครื่องจักรของรัฐซึ่งคอยติดตามตำแหน่งของผู้ที่ถูกประหารชีวิตเมื่อไม่นานมานี้และคุณค่าของคนในท้องถิ่น ยิ่งไปกว่านั้นในตัวอย่างที่กำหนดคิวการกระทำระดับโลกที่นำมาใช้โดยระบบปฏิบัติการและลูปข้อความซึ่งดำเนินการกระทำเหล่านั้น
แบบฝึกหัด: คุณคิดว่าทั้งหมดนี้ทำงานได้อย่างไรในโลกที่ไม่มีลูปข้อความ? ตัวอย่างเช่นแอปพลิเคชันคอนโซล รอในแอปคอนโซลค่อนข้างแตกต่าง คุณสามารถอนุมานว่ามันทำงานอย่างไรจากสิ่งที่คุณรู้จนถึงตอนนี้?
เมื่อฉันได้เรียนรู้เกี่ยวกับปีที่ผ่านมากองอยู่ที่นั่นเพราะมันเร็วฟ้าผ่าและมีน้ำหนักเบาชิ้นส่วนของหน่วยความจำที่จัดสรรที่แอพพลิเคชั่นห่างจากกองเพราะมันรองรับการจัดการที่มีประสิทธิภาพสูงสำหรับงานในมือ มีอะไรเปลี่ยนแปลงบ้าง?
สแต็คเป็นโครงสร้างข้อมูลที่มีประโยชน์เมื่ออายุการใช้งานของวิธีการเปิดใช้งานในรูปแบบสแต็ก แต่ในตัวอย่างของฉันการเปิดใช้งานตัวจัดการคลิก Foo, Bar และ Blah ไม่ได้สร้างสแต็ก ดังนั้นโครงสร้างข้อมูลที่แสดงว่าเวิร์กโฟลว์ไม่สามารถเป็นสแต็กได้ ค่อนข้างจะเป็นกราฟของงานที่ได้รับการจัดสรรฮีปและผู้ได้รับมอบหมายที่แสดงถึงเวิร์กโฟลว์ การรอคอยคือจุดในเวิร์กโฟลว์ที่ไม่สามารถดำเนินการต่อไปในเวิร์กโฟลว์จนกว่างานที่เริ่มต้นก่อนหน้านี้จะเสร็จสมบูรณ์ ในขณะที่เรากำลังรอเราสามารถดำเนินการงานอื่น ๆที่ไม่ขึ้นอยู่กับงานเริ่มต้นเหล่านั้นหลังจากเสร็จสิ้น
สแต็คเป็นเพียงอาร์เรย์ของเฟรมโดยที่เฟรมมีตัวชี้ (1) ถึงกึ่งกลางของฟังก์ชั่น (ที่มีการเรียกเกิดขึ้น) และ (2) ค่าของตัวแปรท้องถิ่นและอุณหภูมิ งานต่อเนื่องเป็นสิ่งเดียวกัน: ผู้รับมอบสิทธิ์เป็นตัวชี้ไปยังฟังก์ชั่นและมีสถานะที่อ้างอิงถึงจุดเฉพาะในช่วงกลางของฟังก์ชั่น . เฟรมไม่ได้เรียงเป็นระเบียบเรียบร้อยดีอีกต่อไป แต่ข้อมูลทั้งหมดเหมือนกัน