ถ้าไม่มีคำหลักล่ะ?
ฉันต้องการให้คอมไพเลอร์ตระหนักว่าส่วนใหญ่เวลาที่ฉันเรียกใช้วิธีการแบบอะซิงโครนัสฉันต้องการผลลัพธ์ของมัน
Document doc = DownloadDocumentAsync();
แค่นั้นแหละ. สาเหตุที่ผู้คนกำลังคิดหนักใจกับคำหลักสำหรับสิ่งนี้เพราะมันเหมือนมีคำหลักสำหรับ "ทำสิ่งที่คุณทำถ้าสิ่งต่าง ๆ เป็นปกติอย่างสมบูรณ์" นั่นควรเป็นค่าเริ่มต้นไม่จำเป็นต้องมีคำหลัก
ปรับปรุง
ฉันแนะนำว่าคอมไพเลอร์ควรฉลาดด้วยการอนุมานประเภทเพื่อหาว่าจะทำอย่างไร เมื่อพิจารณาเพิ่มเติมเกี่ยวกับเรื่องนี้ฉันจะทำให้การใช้งานที่มีอยู่ใน CTP เป็นเช่นเดิม แต่ทำการเพิ่มเล็กน้อยเข้าไปอีกเล็กน้อยเพื่อลดกรณีที่คุณจำเป็นต้องใช้await
คำหลักอย่างชัดเจน
[AutoAwait]
เราคิดค้นแอตทริบิวต์: สิ่งนี้สามารถใช้ได้กับวิธีการเท่านั้น async
วิธีหนึ่งที่จะได้รับนี้นำไปใช้กับวิธีการของคุณคือการทำเครื่องหมาย แต่คุณสามารถทำได้ด้วยมือเช่น:
[AutoAwait]
public Task<Document> DownloadDocumentAsync()
จากนั้นภายในasync
วิธีการใด ๆคอมไพเลอร์จะถือว่าคุณต้องการรอการโทรถึงDownloadDocumentAsync
ดังนั้นคุณไม่จำเป็นต้องระบุ การเรียกใช้วิธีการนั้นจะรอโดยอัตโนมัติ
Document doc = DownloadDocumentAsync();
ตอนนี้ถ้าคุณต้องการ "รับความฉลาด" และรับสิ่งTask<Document>
นั้นคุณต้องใช้โอเปอเรเตอร์start
ซึ่งสามารถปรากฏได้ก่อนการเรียกใช้เมธอด:
Task<Document> task = start DownloadDocumentAsync();
ฉันคิดว่าเรียบร้อย ตอนนี้การเรียกใช้เมธอดธรรมดาหมายถึงความหมาย: รอวิธีการให้เสร็จสมบูรณ์ และstart
บ่งบอกถึงสิ่งที่แตกต่าง: ไม่ต้องรอ
สำหรับรหัสที่ปรากฏอยู่นอกasync
เมธอดวิธีเดียวที่คุณได้รับอนุญาตให้เรียกใช้[AutoAwait]
เมธอดคือโดยนำหน้าด้วยstart
วิธีนั้น นี่เป็นการบังคับให้คุณเขียนโค้ดที่มีความหมายเหมือนกันไม่ว่าจะปรากฏในasync
วิธีการหรือไม่ก็ตาม
จากนั้นฉันก็เริ่มที่จะโลภ! :)
ประการแรกฉันต้องการasync
นำไปใช้กับวิธีการเชื่อมต่อ:
interface IThing
{
async int GetCount();
}
โดยทั่วไปหมายความว่าวิธีการใช้งานจะต้องส่งคืนTask<int>
หรือสิ่งที่เข้ากันได้กับawait
และผู้โทรไปที่วิธีการจะได้รับ[AutoAwait]
พฤติกรรม
นอกจากนี้เมื่อฉันใช้วิธีการข้างต้นฉันต้องการที่จะสามารถเขียน:
async int GetCount()
ดังนั้นฉันไม่ต้องพูดถึงTask<int>
ว่าเป็นประเภทส่งคืน
นอกจากนี้ฉันต้องการasync
นำไปใช้กับประเภทผู้ได้รับมอบหมาย (ซึ่งหลังจากทั้งหมดเป็นเหมือนอินเทอร์เฟซที่มีวิธีการเดียว) ดังนั้น:
public async delegate TResult AsyncFunc<TResult>();
async
ผู้ร่วมประชุมมี - คุณ guessed มัน - [AutoAwait]
พฤติกรรม จากasync
วิธีการที่คุณสามารถเรียกมันและมันจะถูกawait
ed โดยอัตโนมัติ(เว้นแต่คุณเลือกที่จะเพียงแค่start
) ดังนั้นถ้าคุณพูดว่า:
AsyncFunc<Document> getDoc = DownloadDocumentAsync;
นั่นเป็นเพียงการทำงาน มันไม่ใช่วิธีการโทร ยังไม่มีการเริ่มงานเลย - async delegate
ไม่ใช่งาน มันเป็นโรงงานสำหรับทำภารกิจ คุณสามารถพูดได้:
Document doc = getDoc();
และนั่นจะเริ่มงานและรอให้งานเสร็จและให้ผลลัพธ์แก่คุณ หรือคุณสามารถพูดว่า:
Task<Document> t = start getDoc();
ดังนั้นสถานที่แห่งหนึ่งในที่ซึ่ง "ประปา" รั่วไหลออกมาก็คือถ้าคุณต้องการสร้างผู้ร่วมงานให้กับasync
วิธีการคุณต้องรู้ว่าจะใช้async delegate
ประเภทใด ดังนั้นFunc
คุณต้องพูดAsyncFunc
แทนและอื่น ๆ แม้ว่าสักวันหนึ่งสิ่งนั้นอาจได้รับการแก้ไขโดยการอนุมานประเภทที่ปรับปรุงแล้ว
คำถามอื่นคือสิ่งที่จะเกิดขึ้นถ้าคุณบอกว่าเริ่มต้นด้วยวิธีธรรมดา (ไม่ async) เห็นได้ชัดว่าข้อผิดพลาดในการรวบรวมจะเป็นตัวเลือกที่ปลอดภัย แต่มีความเป็นไปได้อื่น ๆ