เหตุใด C # ช่วยให้คุณสามารถแทนที่ async ได้


16

ใน C # เมื่อคุณแทนที่เมธอดจะอนุญาตให้ทำการแทนที่ async เมื่อไม่ได้ใช้วิธีดั้งเดิม ดูเหมือนว่ารูปแบบไม่ดี

ตัวอย่างที่นำฉันมาสู่สิ่งนี้คือสิ่งนี้ - ฉันถูกนำตัวเข้ามาเพื่อช่วยแก้ไขปัญหาการทดสอบโหลด มีผู้ใช้งานพร้อมกันประมาณ 500 คนกระบวนการเข้าสู่ระบบจะแยกย่อยในการวนรอบการเปลี่ยนเส้นทาง IIS กำลังบันทึกข้อยกเว้นด้วยข้อความ "โมดูลหรือตัวจัดการแบบอะซิงโครนัสเสร็จสมบูรณ์ในขณะที่การดำเนินการแบบอะซิงโครนัสยังคงค้างอยู่" การค้นหาบางอย่างทำให้ฉันคิดว่ามีใครบางคนกำลังดูถูกเหยียดหยามasync voidแต่การค้นหาอย่างรวดเร็วของฉันผ่านทางแหล่งข้อมูลไม่พบสิ่งใดเลย

น่าเศร้าที่ฉันกำลังค้นหา 'async \ svoid' (การค้นหา regex) เมื่อฉันควรมองหาบางสิ่งเพิ่มเติมเช่น 'async \ s [^ T]' (สมมติว่า Task ไม่ผ่านการรับรอง ... คุณเข้าใจแล้ว)

สิ่งที่ฉันพบภายหลังคือasync override void onActionExecuting(...ตัวควบคุมพื้นฐาน เห็นได้ชัดว่าจะต้องมีปัญหาและมันก็เป็น แก้ไขปัญหาที่เกิดขึ้น (ทำให้ซิงโครนัสสักครู่) แก้ไขปัญหา

กลับไปที่คำถาม: ทำไมโอทำไมคุณสามารถทำเครื่องหมาย override เป็น async เมื่อรหัสการโทรไม่สามารถรอได้?



สิ่งใดยับยั้งผู้โทรให้รอวิธีการเขียนทับ? ฉันไม่เห็นอุปสรรค
Martin Maat

@MartinMaat คุณสามารถรอวิธีการที่ส่งคืนTaskได้เท่านั้น
Derek Elkins ออกจาก SE

อาจเป็นจุดที่ดีที่ฉันไม่ได้สังเกต ฉันต้องตรวจสอบ แต่ฉันจำการเตือน VS ไม่ได้เกี่ยวกับการเรียกใช้วิธีการที่ไม่ใช่แบบอะซิงโครนัสโดยไม่รอ
Peter T. LaComb Jr.

คำตอบ:


16

asyncคำหลักที่ช่วยให้วิธีการใช้awaitไวยากรณ์ที่อยู่ในความหมายของมัน ฉันสามารถawaitใช้วิธีใดก็ได้ที่ส่งคืนTaskประเภทโดยไม่คำนึงว่าเป็นวิธีการแบบอะซิงก์หรือไม่

voidประเภทผลตอบแทนทางกฎหมาย (ถึงแม้ว่าจะหมดกำลังใจ ) สำหรับวิธีการแบบอะซิงก์ดังนั้นทำไมจึงไม่อนุญาตให้ใช้ จากภายนอกasyncไม่ได้เปิดใช้งานสิ่งที่คุณทำไม่ได้ถ้าไม่ทำ วิธีการที่คุณประสบปัญหาอาจถูกเขียนขึ้นเพื่อให้ทำงานเหมือนกันทุกประการโดยไม่ต้องใช้ async คำจำกัดความของมันจะละเอียดมากขึ้น

ให้โทรติดต่อเป็นasync Tวิธีการเป็นวิธีการปกติที่ผลตอบแทนT(ซึ่งจะถูก จำกัดvoid, TaskหรือTask<A>) ว่าเป็นวิธี async ไม่ได้เป็นส่วนหนึ่งของอินเตอร์เฟซ โปรดสังเกตว่ารหัสต่อไปนี้ผิดกฎหมาย:

interface IFoo {
    async void Bar();
}

มัน (หรือรหัสที่คล้ายกันในระดับนามธรรม) สร้างข้อความแสดงข้อผิดพลาดต่อไปนี้ใน VS2012:

โมดิฟายเออร์ 'async' สามารถใช้ได้ในเมธอดที่มีเนื้อหาของข้อความเท่านั้น

ถ้าฉันไม่ได้ตั้งใจที่วิธีการในอินเตอร์เฟซหรือผู้ปกครองระดับที่จะมักจะไม่ตรงกันฉันไม่สามารถใช้asyncในการสื่อสารว่า ถ้าฉันต้องการที่จะใช้มันด้วยawaitไวยากรณ์ฉันจะต้องสามารถมีวิธีการแทนที่ async (ในกรณีที่ระดับผู้ปกครอง)


1
คุณไม่ได้พูดถึงoverrideเลย แต่นั่นเป็นคำถามที่เกี่ยวกับ
นาธาน Tuggy

5
@NathanTuggy จุดทั้งหมดของคำตอบคือasyncไม่ได้เปลี่ยนส่วนต่อประสานของวิธีการเฉพาะสิ่งที่ได้รับอนุญาต syntactically ในคำนิยามของมันดังนั้นไม่ว่าจะเป็นการแทนที่หรือไม่เกี่ยวข้องอย่างสมบูรณ์
Derek Elkins ออกจาก SE

1
โปรดอธิบายว่าแทนที่จะสมมติว่าทุกคนรู้ทุกอย่างที่เกี่ยวข้องแล้ว
Nathan Tuggy

2
@NathanTuggy ฉันรู้สึกว่าฉันอธิบายแล้ว คุณสามารถถามคำถามที่เฉพาะเจาะจงเกี่ยวกับสิ่งที่คุณกำลังสับสนหรือคุณคิดว่าคนอื่นจะสับสนถาม? สิ่งเดียวที่ฉันคิดได้ว่าเพิ่มคือชี้ให้เห็นว่าasyncตัวดัดแปลงสามารถใช้ได้กับการใช้งานเท่านั้น คุณไม่สามารถประกาศเมธอด async ในอินเทอร์เฟซได้ตัวอย่างเช่นการเน้นว่าเมธอดนั้นเป็น async หรือไม่นั้นไม่ได้เป็นส่วนหนึ่งของอินเตอร์เฟส
Derek Elkins ออกจาก SE

5
ใส่คำอธิบายในคำตอบฉันหมายถึง นั่นไม่ใช่สิ่งที่ความคิดเห็นมีไว้สำหรับในระยะยาว
Nathan Tuggy

10

จุดประสงค์เดียวของคีย์เวิร์ด async คือรอให้อยู่ในเนื้อหาของฟังก์ชั่นนั้น สิ่งนี้จำเป็นสำหรับการเพิ่มฟังก์ชั่นการรอคอยไม่ทำให้รหัสที่มีอยู่เสียหาย Microsoft ตัดสินใจใช้ประโยชน์จากตัวเลือกการรอคอย สำหรับฟังก์ชั่นที่ไม่ได้ทำเครื่องหมาย async คุณสามารถกำหนดตัวแปรที่ชื่อว่าคอยโดยไม่มีปัญหา

ดังนั้น async ไม่ได้เป็นส่วนหนึ่งของลายเซ็นของฟังก์ชั่นและไม่มีความหมายเชิงความหมายในรหัส IL ที่สร้างขึ้น มันมีอย่างเคร่งครัดสำหรับคอมไพเลอร์ที่จะรู้วิธีการรวบรวมฟังก์ชั่นอย่างถูกต้อง นอกจากนี้ยังสั่งคอมไพเลอร์เพื่อให้แน่ใจว่าจะส่งคืนเฉพาะภารกิจงาน <T> หรือโมฆะเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.