แนวทางของ async / ไม่ใช้งานการรอคอยใน C # ขัดแย้งกับแนวคิดของสถาปัตยกรรมที่ดีและการฝังรากลึกนามธรรม?


103

คำถามนี้เกี่ยวกับภาษา C # แต่ฉันคาดหวังให้ครอบคลุมภาษาอื่นเช่น Java หรือ TypeScript

Microsoft แนะนำแนวทางปฏิบัติที่ดีที่สุดในการใช้การโทรแบบอะซิงโครนัสใน. NET ในบรรดาคำแนะนำเหล่านี้เรามาเลือกสองข้อ:

  • เปลี่ยนลายเซ็นของเมธอด async เพื่อให้ส่งคืนงานหรืองาน <> (ใน TypeScript นั่นจะเป็นสัญญา <>)
  • เปลี่ยนชื่อของวิธีการ async เป็นลงท้ายด้วย xxxAsync ()

ตอนนี้เมื่อแทนที่ส่วนประกอบที่มีระดับต่ำและซิงโครนัสด้วยอะซิงก์หนึ่งสิ่งนี้จะส่งผลกระทบต่อสแต็กเต็มของแอปพลิเคชัน เนื่องจาก async / await มีผลกระทบเชิงบวกต่อเมื่อใช้ "all-up up" เท่านั้นนั่นหมายถึงชื่อลายเซ็นและเมธอดของทุกเลเยอร์ในแอปพลิเคชันจะต้องเปลี่ยน

สถาปัตยกรรมที่ดีมักจะเกี่ยวข้องกับการวาง abstractions ระหว่างแต่ละเลเยอร์เช่นการแทนที่ส่วนประกอบระดับต่ำโดยผู้อื่นจะมองไม่เห็นโดยส่วนประกอบระดับบน ใน C # abstractions จะอยู่ในรูปของอินเตอร์เฟส หากเราแนะนำส่วนประกอบ async ใหม่ระดับต่ำและต่ำแต่ละอินเตอร์เฟสใน call stack จำเป็นต้องได้รับการแก้ไขหรือแทนที่ด้วยอินเตอร์เฟสใหม่ วิธีการแก้ไขปัญหา (async หรือ sync) ในชั้นเรียนการใช้งานจะไม่ถูกซ่อน (abstracted) กับผู้โทรอีกต่อไป ผู้โทรต้องทราบว่าซิงค์หรือไม่

async / รอปฏิบัติที่ดีที่สุดไม่ตรงข้ามกับหลักการ "สถาปัตยกรรมที่ดี" หรือไม่?

หมายความว่าแต่ละอินเทอร์เฟซ (พูดว่า IEnumerable, IDataAccessLayer) จำเป็นต้องมีการซิงค์แบบอะซิงโครนัส (IAsyncEnumerable, IAsyncDataAccessLayer) เพื่อให้สามารถแทนที่ในสแต็กเมื่อสลับเป็นการพึ่งพาแบบอะซิงโครนัส

หากเราผลักดันปัญหาไปอีกสักหน่อยคงไม่เป็นการง่ายกว่าที่จะสมมติว่าทุกวิธีเป็นแบบซิงค์ (เพื่อส่งคืนภารกิจ <> หรือสัญญา <>) และสำหรับวิธีการซิงโครไนซ์การโทรแบบอะซิงโครไนซ์เมื่อไม่จริง async? นี่เป็นสิ่งที่คาดหวังจากภาษาการเขียนโปรแกรมในอนาคตหรือไม่


5
ในขณะที่สิ่งนี้ดูเหมือนคำถามการสนทนาที่ยอดเยี่ยม แต่ฉันคิดว่านี่เป็นคำตอบที่ไม่เหมาะสม
Euphoric

22
@Euphoric: ฉันคิดว่าปัญหาที่ฝังลึกลงไปในแนวทางนี้ลึกกว่าแนวทาง C # นั่นเป็นเพียงอาการของความจริงที่ว่าการเปลี่ยนบางส่วนของแอปพลิเคชันเป็นพฤติกรรมอะซิงโครนัสอาจมีผลกระทบที่ไม่ใช่ท้องถิ่นต่อระบบโดยรวม ดังนั้นลำไส้ของฉันบอกฉันว่าจะต้องมีคำตอบที่ไม่ใช่ความเห็นสำหรับเรื่องนี้ขึ้นอยู่กับข้อเท็จจริงทางเทคนิค ดังนั้นฉันขอแนะนำให้ทุกคนที่นี่ที่จะไม่ปิดคำถามนี้เร็วเกินไปแทนที่จะให้เรารอสิ่งที่คำตอบจะมา (และหากพวกเขามีความเห็นมากเกินไปเรายังสามารถลงคะแนนให้ปิด)
Doc Brown

25
@DocBrown ฉันคิดว่าคำถามที่ลึกกว่านี้คือ "สามารถเปลี่ยนบางส่วนของระบบจากแบบซิงโครนัสเป็นแบบอะซิงโครนัสโดยไม่ต้องมีส่วนที่ต้องเปลี่ยนได้หรือไม่" ฉันคิดว่าคำตอบนั้นชัดเจนว่า "ไม่" ในกรณีนี้ฉันไม่เห็นว่า "แนวคิดของสถาปัตยกรรมและเลเยอร์ที่ดี" นำไปใช้ที่นี่ได้อย่างไร
ร่าเริง

6
@Euphoric: ดูเหมือนจะเป็นพื้นฐานที่ดีสำหรับคำตอบที่ไม่ใช่ความเห็น ;-)
Doc Brown

5
@Gherman: เนื่องจาก C # เหมือนกับภาษาจำนวนมากไม่สามารถทำการโหลดมากเกินไปตามประเภทการคืนเท่านั้น คุณจะจบลงด้วยวิธีการ async ที่มีลายเซ็นเหมือนกันกับการซิงค์ (ไม่สามารถทำได้ทั้งหมดCancellationTokenและผู้ที่อาจต้องการให้เป็นค่าเริ่มต้น) การลบวิธีการซิงค์ที่มีอยู่ (และทำลายรหัสทั้งหมดในเชิงรุก) เป็นสิ่งที่ไม่ใช่การเริ่มต้นที่ชัดเจน
Jeroen Mostert

คำตอบ:


111

ฟังก์ชั่นของคุณสีอะไร?

คุณอาจจะสนใจในบ๊อบ Nystrom ของสีคืออะไรฟังก์ชั่นของคุณ 1

ในบทความนี้เขาอธิบายภาษาสมมติที่:

  • แต่ละฟังก์ชั่นมีสี: สีน้ำเงินหรือสีแดง
  • ฟังก์ชั่นสีแดงอาจเรียกใช้ฟังก์ชั่นสีน้ำเงินหรือสีแดงไม่มีปัญหา
  • ฟังก์ชั่นสีน้ำเงินอาจเรียกฟังก์ชั่นสีน้ำเงินเท่านั้น

ในขณะที่สมมติขึ้นสิ่งนี้เกิดขึ้นค่อนข้างสม่ำเสมอในภาษาการเขียนโปรแกรม:

  • ใน C ++ เมธอด "const" อาจเรียกเมธอด "const" thisอื่นเท่านั้น
  • ใน Haskell ฟังก์ชันที่ไม่ใช่ IO อาจเรียกใช้ฟังก์ชันที่ไม่ใช่ IO เท่านั้น
  • ใน C # ฟังก์ชั่นการซิงค์อาจเรียกใช้ฟังก์ชั่นการซิงค์2เท่านั้น

ดังที่คุณทราบเนื่องจากกฎเหล่านี้ฟังก์ชั่นสีแดงมักจะแพร่กระจายไปทั่วฐานรหัส คุณแทรกหนึ่งและทีละน้อยมันอาณานิคมฐานรหัสทั้งหมด

1 Bob Nystrom นอกเหนือจากบล็อกแล้วยังเป็นส่วนหนึ่งของทีม Dart และได้เขียนเซเรียอาคราฟต์ตัวน้อยนี้ แนะนำเป็นอย่างยิ่งสำหรับภาษาการเขียนโปรแกรม / afficionado ใด ๆ

2 ไม่จริงอย่างที่คุณอาจเรียกใช้ฟังก์ชัน async และบล็อกจนกว่ามันจะกลับมา แต่ ...

ข้อ จำกัด ทางภาษา

นี่คือข้อ จำกัด ทางภาษา / เวลาทำงาน

ภาษาที่มี M: N เธรดตัวอย่างเช่น Erlang และ Go ไม่มีasyncฟังก์ชั่น: แต่ละฟังก์ชั่นอาจเป็นแบบอะซิงก์และ "ไฟเบอร์" ของมันจะถูกระงับชั่วคราวสลับและสลับกลับมาเมื่อพร้อมอีกครั้ง

C # ไปกับโมเดลการทำเกลียว 1: 1 และดังนั้นจึงตัดสินใจที่จะซิงโครไนซ์ในภาษาเพื่อหลีกเลี่ยงการบล็อกเธรดโดยไม่ตั้งใจ

เมื่อมีข้อ จำกัด ด้านภาษาแนวทางการเข้ารหัสต้องปรับเปลี่ยน


4
ฟังก์ชั่น IO มีแนวโน้มที่จะแพร่กระจาย แต่ด้วยความขยันคุณสามารถแยกพวกเขาไปทำงานใกล้จุดเข้า (ในสแต็กเมื่อโทร) ส่วนใหญ่ของโค้ดของคุณ คุณสามารถทำได้โดยให้ฟังก์ชั่นเหล่านั้นเรียกใช้ฟังก์ชั่น IO จากนั้นให้ฟังก์ชั่นอื่นประมวลผลเอาต์พุตจากพวกเขาและส่งคืนผลลัพธ์ใด ๆ ที่จำเป็นสำหรับ IO เพิ่มเติม ฉันพบว่าสไตล์นี้ทำให้รหัสของฉันง่ายต่อการจัดการและทำงานกับ ฉันสงสัยว่ามีการพิสูจน์ด้วยบังเอิญหรือไม่
jpmc26

16
คุณหมายถึงอะไรโดยการทำเกลียว "M: N" และ "1: 1"
กัปตัน Man

14
@CaptainMan: เธรด 1: 1 หมายถึงการแม็พเธรดแอ็พพลิเคชันหนึ่งเธรดกับ OS หนึ่งเธรดซึ่งเป็นกรณีในภาษาเช่น C, C ++, Java หรือ C # ในทางตรงกันข้าม M: N เธรดหมายถึงการแม็พแอ็พพลิเคชันเธรด M กับเธรด OS OS ในกรณีของ Go แอปพลิเคชันเธรดเรียกว่า "goroutine" ในกรณีของ Erlang มันถูกเรียกว่า "นักแสดง" และคุณอาจเคยได้ยินว่าเป็น "เธรดสีเขียว" หรือ "เส้นใย" พวกเขาให้เห็นพ้องด้วยโดยไม่ต้องขนาน น่าเสียดายบทความ Wikipedia ในหัวข้อค่อนข้างกระจัดกระจาย
Matthieu M.

2
สิ่งนี้เกี่ยวข้องกันบ้าง แต่ฉันคิดว่าแนวคิด "ฟังก์ชั่นสี" นี้ใช้กับฟังก์ชั่นที่บล็อกการป้อนข้อมูลจากผู้ใช้เช่นกล่องโต้ตอบโมดอลกล่องข้อความรูปแบบคอนโซล I / O บางรูปแบบเป็นต้นซึ่งเป็นเครื่องมือที่ กรอบได้มีตั้งแต่จุดเริ่มต้น
jrh

2
@MatthieuM C # ไม่มีแอปพลิเคชันเธรดเดียวต่อหนึ่งเธรด OS และไม่เคยทำ นี้เป็นที่ชัดเจนมากเมื่อคุณมีปฏิสัมพันธ์กับรหัสพื้นเมืองและโดยเฉพาะอย่างยิ่งเห็นได้ชัดเมื่อทำงานใน MS SQL และแน่นอนกิจวัตรความร่วมมือเป็นไปได้เสมอ (และง่ายกว่าด้วยasync) จริง ๆ แล้วมันเป็นรูปแบบที่ใช้กันทั่วไปในการสร้าง UI ที่ตอบสนองได้ มันสวยเหมือน Erlang ไหม? Nope แต่นั่นก็ยังห่างไกลจาก C :)
Luaan

82

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


27
คำตอบนั้นง่ายเหมือน IMO นี้ ความแตกต่างระหว่างกระบวนการแบบซิงโครนัสและแบบอะซิงโครนัสไม่ใช่รายละเอียดการนำไปใช้งาน แต่เป็นสัญญาที่แตกต่างกันในเชิงความหมาย
Ant P

11
@AntP: ฉันไม่เห็นด้วยว่ามันง่ายขนาดนั้น มันแสดงในภาษา C # แต่ไม่ใช่ในภาษา Go ตัวอย่างเช่น ดังนั้นนี่ไม่ใช่คุณสมบัติโดยธรรมชาติของกระบวนการแบบอะซิงโครนัสมันเป็นเรื่องของวิธีการแบบอะซิงโครนัสแบบจำลองในภาษาที่กำหนด
Matthieu M.

1
@MatthieuM ใช่ แต่คุณสามารถใช้asyncวิธีการใน C # เพื่อจัดทำสัญญาแบบซิงโครนัสได้เช่นกันหากคุณต้องการ ความแตกต่างเพียงอย่างเดียวคือการใช้งานแบบอะซิงโครนัสตามค่าเริ่มต้นในขณะที่ C # จะซิงโครนัสตามค่าเริ่มต้น asyncให้รูปแบบการเขียนโปรแกรมที่สอง - async เป็นนามธรรม (สิ่งที่จริงมันขึ้นอยู่กับรันไทม์, กำหนดการงานบริบทการประสานการใช้งานพนักงานเสิร์ฟ ... )
Luaan

6

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

ในความรู้สึกมันก็เหมือนมีวิธีการที่โยนข้อยกเว้นและอื่น ๆ ที่ "ปลอดภัย" และจะไม่โยนแม้ในกรณีที่มีข้อผิดพลาด coder มีมากเกินไปที่จุดใดเพื่อให้วิธีการเหล่านี้ซึ่งมิฉะนั้นสามารถแปลงหนึ่งไปยังอีก?

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

หากคุณอยู่ในโรงเรียนแห่งแรกมีตรรกะบางอย่างที่จะอุทิศชั้นเรียนเพื่อการโทรแบบซิงโครนัสและอะซิงโครนัสเพื่อหลีกเลี่ยงการโทรทุกครั้งเป็นสองเท่า Microsoft มีแนวโน้มที่จะสนับสนุนโรงเรียนแห่งความคิดนี้และโดยการประชุมเพื่อให้สอดคล้องกับสไตล์ที่ Microsoft โปรดปรานคุณก็จะต้องมีเวอร์ชัน Async ด้วยวิธีเดียวกันกับที่อินเตอร์เฟสมักจะเริ่มต้นด้วย "I" ฉันขอย้ำว่ามันไม่ผิดเลยเพราะมันเป็นการดีกว่าที่จะรักษาสไตล์ที่สอดคล้องกันในโครงการแทนที่จะทำ "วิธีที่ถูกต้อง" และเปลี่ยนสไตล์การพัฒนาที่คุณเพิ่มเข้าไปในโครงการอย่างสิ้นเชิง

ที่กล่าวว่าฉันมักจะชอบโรงเรียนที่สองซึ่งจะลดวิธีการอินเตอร์เฟซ ถ้าฉันคิดว่าวิธีการอาจถูกเรียกในลักษณะอะซิงโครนัสวิธีสำหรับฉันคือไม่ตรงกัน ผู้เรียกสามารถตัดสินใจว่าจะรอให้ภารกิจนั้นเสร็จสิ้นก่อนที่จะดำเนินการต่อหรือไม่ หากอินเทอร์เฟซนี้เป็นอินเทอร์เฟซไปยังไลบรารีมีเหตุผลมากกว่าที่จะทำเช่นนี้เพื่อลดจำนวนวิธีที่คุณต้องการลดค่าใช้จ่ายหรือปรับเปลี่ยน หากอินเทอร์เฟซสำหรับการใช้งานภายในในโครงการของฉันฉันจะเพิ่มวิธีการสำหรับการโทรทุกครั้งที่จำเป็นสำหรับโครงการของฉันสำหรับพารามิเตอร์ที่ให้ไว้และไม่มีวิธี "พิเศษ" และแม้กระทั่งถ้าพฤติกรรมของวิธีการไม่ครอบคลุม โดยวิธีการที่มีอยู่

อย่างไรก็ตามเช่นเดียวกับหลายสิ่งในสาขานี้มันเป็นเรื่องส่วนตัว ทั้งสองวิธีมีข้อดีข้อเสีย ไมโครซอฟท์ก็เริ่มการประชุมของการเพิ่มตัวอักษรที่บ่งบอกถึงประเภทที่จุดเริ่มต้นของชื่อตัวแปรและ "m_" m_pUserเพื่อแสดงว่าเป็นสมาชิกคนหนึ่งที่นำไปสู่ชื่อตัวแปรเช่น ประเด็นของฉันคือแม้กระทั่ง Microsoft ก็ไม่ผิดพลาดและสามารถทำผิดพลาดได้เช่นกัน

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


6
"ที่รันไทม์การแปลงการโทรแบบ async เป็นแบบซิงโครนัสเป็นเรื่องเล็กน้อย" ฉันไม่แน่ใจว่ามันจะเป็นแบบนั้น ใน. NET การใช้.Wait()วิธีการและชอบอาจทำให้เกิดผลกระทบเชิงลบและใน js เท่าที่ฉันรู้มันเป็นไปไม่ได้เลย
สูงสุด 630

2
@ max630 ฉันไม่ได้บอกว่าไม่มีปัญหาที่เกิดขึ้นพร้อมกันในการพิจารณา แต่ถ้ามันเป็นงานที่ต้องทำแบบซิงโครนัสในขั้นต้นโอกาสที่มันจะไม่เกิดการหยุดชะงัก ที่กล่าวว่าไม่สำคัญไม่ได้หมายความว่า "ดับเบิลคลิกที่นี่เพื่อแปลงเป็นซิงโครนัส" ใน js คุณจะส่งคืนอินสแตนซ์ของ Promise และโทรแก้ปัญหา
Neil

2
ใช่มันเป็นความเจ็บปวดโดยสิ้นเชิงในการแปลง async กลับไปซิงค์
Ewan

4
@Neil ในจาวาสคริปต์แม้ว่าคุณจะโทรPromise.resolve(x)แล้วเพิ่มการโทรกลับเข้าไป แต่การโทรกลับเหล่านั้นจะไม่ถูกดำเนินการในทันที
NickL

1
@Neil หากอินเตอร์เฟสแสดงวิธีการแบบอะซิงโครนัสโดยคาดว่าการรองานจะไม่สร้างการหยุดชะงักไม่ถือว่าเป็นข้อสมมติที่ดี จะดีกว่ามากสำหรับอินเทอร์เฟซที่จะแสดงว่าจริง ๆ แล้วซิงโครนัสในลายเซ็นวิธีการกว่าสัญญาในเอกสารประกอบที่อาจเปลี่ยนแปลงในรุ่นที่ใหม่กว่า
Carl Walsh

2

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

นั่นจะเจ๋งจริงๆและไม่มีใครแนะนำให้คุณเปลี่ยนชื่อ

แต่ฟังก์ชั่นอะซิงโครนัสที่เกิดขึ้นจริงไม่ใช่แค่ฟังก์ชั่นที่รอฟังก์ชั่นอะซิงก์อีกตัว แต่ระดับต่ำสุดมีโครงสร้างบางอย่างที่เฉพาะเจาะจงกับลักษณะอะซิงก์ เช่น

public class HTTPClient
{
    public HTTPResponse GET()
    {
        //send data
        while(!timedOut)
        {
            //check for response
            if(response) { 
                this.GotResponse(response); 
            }
            this.YouCanWait();
        }
    }

    //tell calling code that they should watch for this event
    public EventHander GotResponse
    //indicate to calling code that they can go and do something else for a bit
    public EventHander YouCanWait;
}

เป็นข้อมูลสองบิตที่รหัสการโทรต้องการเพื่อเรียกใช้รหัสในแบบอะซิงก์ที่สิ่งต่าง ๆ เช่นTaskและasyncแค็ปซูล

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


0

ฉันจะพูดถึงประเด็นหลักในรูปแบบ C # Ness ที่น้อยลงและเป็นเรื่องทั่วไปมากขึ้น:

async / รอปฏิบัติที่ดีที่สุดไม่ตรงข้ามกับหลักการ "สถาปัตยกรรมที่ดี" หรือไม่?

ฉันจะบอกว่ามันขึ้นอยู่กับตัวเลือกที่คุณเลือกในการออกแบบ API และสิ่งที่คุณให้กับผู้ใช้

หากคุณต้องการให้หนึ่งฟังก์ชันของ API ของคุณเป็นแบบอะซิงก์เพียงอย่างเดียวความสนใจเพียงเล็กน้อยในการติดตามการตั้งชื่อจะเป็นอย่างไร เพียงแค่ส่งคืนงาน <> / สัญญา <> / อนาคต <> / ... เป็นประเภทส่งคืนเสมอมันเป็นเอกสารด้วยตนเอง หากต้องการคำตอบแบบซิงโครไนซ์เขาจะยังคงสามารถทำได้โดยรอ แต่ถ้าเขาทำอย่างนั้นตลอดมันจะทำให้หม้อไอน้ำเล็กน้อย

อย่างไรก็ตามหากคุณทำการซิงค์ API ของคุณเท่านั้นนั่นหมายความว่าหากผู้ใช้ต้องการให้เป็นแบบอะซิงโครนัสเขาจะต้องจัดการส่วน async ของมันเอง

สิ่งนี้สามารถทำงานได้ค่อนข้างมาก แต่ก็สามารถควบคุมผู้ใช้ได้มากขึ้นเกี่ยวกับจำนวนการโทรพร้อมกันที่เขาอนุญาตวางหมดเวลา retrys และอื่น ๆ

ในระบบขนาดใหญ่ที่มี API ขนาดใหญ่การใช้งานส่วนใหญ่ในการซิงค์โดยค่าเริ่มต้นอาจทำได้ง่ายกว่าและมีประสิทธิภาพมากกว่าการจัดการแต่ละส่วนของ API ของคุณโดยเฉพาะอย่างยิ่งหากพวกเขาแบ่งปันทรัพยากรระบบไฟล์ (CPU ระบบฐานข้อมูล ... )

ในความเป็นจริงสำหรับชิ้นส่วนที่ซับซ้อนที่สุดคุณสามารถมีการใช้งานสองส่วนที่เหมือนกันของ API ของคุณหนึ่งแบบซิงโครนัสทำสิ่งที่มีประโยชน์หนึ่งแบบอะซิงโครนัสที่อาศัยแบบซิงโครนัส .

บางทีคนอื่นสามารถแบ่งปันประสบการณ์ของเขากับที่เพราะฉันขาดประสบการณ์กับระบบดังกล่าว


2
@Miral คุณได้ใช้ "เรียกวิธีการ async จากวิธีการซิงค์" ทั้งสองวิธี
Adrian Wragg

@AdrianWragg ดังนั้นฉันทำ; สมองของฉันต้องมีสภาพการแข่งขัน ฉันจะแก้ไข
Miral

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

(และโดยวิธีนี้ฉันหมายถึงวิธีการบล็อกการทำข้อมูลให้ตรงกันคุณสามารถเรียกสิ่งที่ทำให้การคำนวณที่มีขอบเขต CPU บริสุทธิ์แบบซิงโครนัสจากวิธีการแบบอะซิงโครนัส - แม้ว่าคุณควรพยายามหลีกเลี่ยง มากกว่าบริบท UI - แต่การปิดกั้นสายที่รอไม่ได้ใช้งานในการล็อคหรือ I / O หรือการดำเนินการอื่นที่มีความคิดที่ไม่ดี).
Miral
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.