การเรียกไลบรารี async อาศัยซึ่งกันและกันและวิธีจัดการ?

นี่เป็นการติดตามจากคำถามก่อนหน้าที่ฉันโพสต์ การโทร วิธี async โดยใช้ Task.Run ดูเหมือนจะผิดใช่ไหม

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

เพื่ออธิบายห้องสมุดของฉันมีวิธีการ:

public Task<TemplateInfo> TemplateInfo(TemplateInfoRequest request);
public Task<List<EmailResult>> SendMessageTemplate(SendMessageTemplateRequest request);

ฉันต้องเรียกสิ่งเหล่านี้ว่า:

public bool SendMessage()
{
  var template = TemplateInfo(...);
  var message = //use template to create message
  var sendResponse = SendMessageTemplate(message);

   return sendResponse.Count > 0;
}

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

คำตอบในคำถามก่อนหน้าของฉันยังระบุด้วย:

เนื่องจากคุณกำลังบล็อกวิธีอะซิงก์ (ซึ่งคุณไม่ควรทำ) จึงมีโอกาสที่คุณจะเกิดการหยุดชะงัก

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


person Liam    schedule 16.09.2015    source แหล่งที่มา
comment
เลียมคุณสับสนมากมาก Async ไม่ได้หมายความว่าเกิดขึ้นพร้อมกัน   -  person Aron    schedule 16.09.2015
comment
@Aron: Asynchrony เป็นรูปแบบหนึ่งของการทำงานพร้อมกัน อย่างไรก็ตาม ความไม่ตรงกันไม่เหมือนกับ ความขนาน   -  person Stephen Cleary    schedule 17.09.2015


คำตอบ (1)


Async ไม่ได้ (จำเป็น) หมายถึงการขนาน

คุณสามารถเรียกเมธอด async ทั้งสองได้ ตามลำดับ โดยที่ไม่ต้องทำงานพร้อมกัน เพียงโทรหาคนแรกและรองานที่ส่งคืน จากนั้นทำเช่นเดียวกันกับงานที่สอง

var template = await TemplateInfo(...);
var message = //use template to create message
var sendResponse = await SendMessageTemplate(message);

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

หากคุณจะโทรทั้งสองและเพียงรองานที่ส่งคืนคุณ (อาจจะ) ทำงานแบบขนาน:

var templateTask = TemplateInfo(...);
var sendResponseTask = SendMessageTemplate(message);
await templateTask;
await sendResponseTask;
person i3arnon    schedule 16.09.2015
comment
ฉันขอแนะนำให้คุณเพิ่มเล็กน้อยเกี่ยวกับ I/O แบบอะซิงก์แบบไม่บล็อกเพื่อล้างข้อดีของอะซิงก์ตามลำดับ - person Aron; 16.09.2015
comment
แต่หากต้องการเพิ่ม await ฉันต้องทำเครื่องหมายวิธีการของฉันเป็น async และส่งคืน Task ฉันแค่ต้องการค่าเดียวพร้อมกัน ฉันจะใช้ .Result แต่แล้วฉันก็บล็อก async ใช่ไหม ซึ่งฉันคิดว่าฉันไม่ควรทำ ฉันได้เพิ่มรายละเอียดในคำถามแล้ว - person Liam; 16.09.2015
comment
ฉันคิดว่าฉันสับสน เมื่อถึงจุดหนึ่งฉันต้องหยุดเรียกใช้เมธอด async และเพื่อให้มันซิงโครไนซ์ หรือฉันจะแจ้งให้ผู้ใช้ทราบได้อย่างไรว่าเกิดอะไรขึ้น แล้วฉันจะออกจากสิ่งนี้ได้อย่างงดงามโดยไม่ปิดกั้นได้อย่างไร - person Liam; 16.09.2015
comment
@Liam ตัวเลือกที่ดีที่สุดคือ async ขึ้นไปจนสุด สิ่งนี้จำเป็นต้องเปลี่ยนการเรียกเมธอดจนกว่าคุณจะไปถึงจุดสูงสุด (ซึ่งอาจเป็นตัวจัดการเหตุการณ์ Main เป็นต้น) หากคุณไม่สามารถทำเช่นนั้นได้ด้วยเหตุผลบางประการ ตัวเลือกถัดไปคืออย่าใช้อะซิงก์เลยและใช้โค้ดซิงโครนัสลงไปจนสุด หากนั่นไม่ใช่ตัวเลือก (เนื่องจากคุณใช้ไลบรารีที่มี API แบบอะซิงก์เท่านั้น) คุณจะไม่มีตัวเลือกอื่นใดนอกจากการบล็อกโค้ดอะซิงก์ จากนั้นลองตรวจสอบให้แน่ใจว่าทำได้อย่างปลอดภัย - person i3arnon; 16.09.2015