ถ้าไม่มีคำหลักล่ะ?
ฉันต้องการให้คอมไพเลอร์ตระหนักว่าส่วนใหญ่เวลาที่ฉันเรียกใช้วิธีการแบบอะซิงโครนัสฉันต้องการผลลัพธ์ของมัน
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วิธีการที่คุณสามารถเรียกมันและมันจะถูกawaited โดยอัตโนมัติ(เว้นแต่คุณเลือกที่จะเพียงแค่start) ดังนั้นถ้าคุณพูดว่า:
AsyncFunc<Document> getDoc = DownloadDocumentAsync;
นั่นเป็นเพียงการทำงาน มันไม่ใช่วิธีการโทร ยังไม่มีการเริ่มงานเลย - async delegateไม่ใช่งาน มันเป็นโรงงานสำหรับทำภารกิจ คุณสามารถพูดได้:
Document doc = getDoc();
และนั่นจะเริ่มงานและรอให้งานเสร็จและให้ผลลัพธ์แก่คุณ หรือคุณสามารถพูดว่า:
Task<Document> t = start getDoc();
ดังนั้นสถานที่แห่งหนึ่งในที่ซึ่ง "ประปา" รั่วไหลออกมาก็คือถ้าคุณต้องการสร้างผู้ร่วมงานให้กับasyncวิธีการคุณต้องรู้ว่าจะใช้async delegateประเภทใด ดังนั้นFuncคุณต้องพูดAsyncFuncแทนและอื่น ๆ แม้ว่าสักวันหนึ่งสิ่งนั้นอาจได้รับการแก้ไขโดยการอนุมานประเภทที่ปรับปรุงแล้ว
คำถามอื่นคือสิ่งที่จะเกิดขึ้นถ้าคุณบอกว่าเริ่มต้นด้วยวิธีธรรมดา (ไม่ async) เห็นได้ชัดว่าข้อผิดพลาดในการรวบรวมจะเป็นตัวเลือกที่ปลอดภัย แต่มีความเป็นไปได้อื่น ๆ