ตกลงนี่คือสิ่งที่ฉันทำ
มีบางสิ่งที่เรียกว่าcoroutinesซึ่งเป็นที่รู้จักกันมานานหลายทศวรรษ ( "นูและกระโดด" คลาส "มานานหลายทศวรรษ") พวกเขาเป็นภาพรวมของโปรแกรมย่อยในเช่นไม่เพียง แต่พวกเขาได้รับและการควบคุมการเปิดตัวในช่วงเริ่มต้นการทำงานและคำสั่งกลับ แต่พวกเขายังทำมันที่เฉพาะจุด ( จุดระงับ ) รูทีนย่อยเป็น coroutine ที่ไม่มีจุดพัก
พวกมันเป็นธรรมดาที่จะใช้กับมาโคร C ดังที่แสดงในบทความต่อไปนี้เกี่ยวกับ ( http://dunkels.com/adam/dunkels06protothreads.pdf ) อ่าน ฉันจะรอ...
บรรทัดล่างของเรื่องนี้คือมาโครสร้างใหญ่switch
และcase
ฉลากที่แต่ละจุดหยุดพัก ที่จุดพักแต่ละจุดฟังก์ชันจะเก็บค่าของcase
ป้ายกำกับที่ตามมาทันทีเพื่อให้ทราบตำแหน่งที่จะดำเนินการต่อในครั้งถัดไปที่มีการเรียกใช้ และจะส่งคืนการควบคุมไปยังผู้โทร
สิ่งนี้จะกระทำโดยไม่แก้ไขการควบคุมการไหลของรหัสที่อธิบายไว้ใน "protothread" อย่างชัดเจน
ลองนึกภาพตอนนี้ว่าคุณมีวงวนใหญ่ที่เรียกว่า "โพรโทเท็น" ทั้งหมดนี้แล้ว
วิธีนี้มีสองข้อเสีย:
- คุณไม่สามารถรักษาสถานะในตัวแปรท้องถิ่นระหว่างการเริ่มต้นใหม่
- คุณไม่สามารถระงับ "protothread" จากความลึกการโทรโดยพลการ (คะแนนการระงับทั้งหมดต้องอยู่ที่ระดับ 0)
มีวิธีแก้ไขเฉพาะหน้าสำหรับทั้งสอง:
- ตัวแปรในท้องที่ทั้งหมดจะต้องถูกดึงขึ้นไปตามบริบทของโปรโตรเธด (บริบทที่ต้องการโดยความจริงที่โปรโตรเดตจะต้องจัดเก็บจุดเริ่มต้นใหม่ต่อไป)
- ถ้าคุณรู้สึกว่าคุณต้องเรียก protothread อื่นจาก protothread ให้ "spawn" เด็ก protothread และพักไว้จนกว่าเด็กจะเสร็จสมบูรณ์
และถ้าคุณมีการสนับสนุนคอมไพเลอร์เพื่อทำงานเขียนใหม่ที่มาโครและวิธีแก้ปัญหาทำได้ดีคุณก็สามารถเขียนรหัสโปรโตรเดรดของคุณได้เช่นเดียวกับที่คุณตั้งใจและใส่จุดระงับด้วยคำสำคัญ
และนี่คือสิ่งที่async
และawait
ทุกอย่างเกี่ยวกับ: การสร้าง coroutines (stackless)
coroutines ใน C # จะ reified เป็นวัตถุของ (ทั่วไปหรือไม่ทั่วไป) Task
ระดับ
ฉันพบว่าคำหลักเหล่านี้ทำให้เข้าใจผิดมาก การอ่านจิตของฉันคือ:
async
เป็น "สงสัย"
await
เป็น "ระงับจนกว่าจะเสร็จสิ้น"
Task
เป็น "อนาคต ... "
ตอนนี้ เราจำเป็นต้องทำเครื่องหมายฟังก์ชันasync
หรือไม่? นอกเหนือจากการบอกว่ามันควรจะทริกเกอร์กลไกการเขียนโค้ดใหม่เพื่อทำให้ฟังก์ชั่นเป็น coroutine แต่ก็ช่วยแก้ไขความคลุมเครือบางอย่าง พิจารณารหัสนี้
public Task<object> AmIACoroutine() {
var tcs = new TaskCompletionSource<object>();
return tcs.Task;
}
สมมติว่าasync
ไม่บังคับนี่เป็น coroutine หรือฟังก์ชั่นปกติหรือไม่? คอมไพเลอร์ควรเขียนใหม่เป็น coroutine หรือไม่? ทั้งสองอาจเป็นไปได้ด้วยความหมายที่แตกต่างกันในที่สุด