Async / Await vs Threads


101

ใน. Net 4.5 Microsoft ได้เพิ่มAsync/Awaitคุณลักษณะใหม่เพื่อลดความซับซ้อนของการเข้ารหัสแบบอะซิงโครนัส อย่างไรก็ตามฉันสงสัย

  1. สามารถAsync/Awaitแทนที่วิธีการใช้งานแบบเก่าได้อย่างสมบูรณ์ Threads?
  2. คือAsync/Awaitความสามารถในการทำอะไรก็ตามThreadสามารถทำแบบไม่พร้อม?
  3. ใช้ได้Async/Awaitเฉพาะกับบางวิธีเช่นWebClient.DownloadStringAsyncหรือฉันสามารถแปลงวิธีการซิงโครนัสเพื่อให้ใช้งานAsync/Awaitได้หรือไม่เพื่อบล็อกเธรดหลัก

2
เธรดและ Async / Await เป็นคุณสมบัติที่ไม่เกี่ยวข้องกัน คุณสามารถรวมเข้าด้วยกันได้ แต่ไม่จำเป็นต้องทำ
dtb

2
ฉันคิดว่า Async / Await กำลังทำสิ่งเดียวกันกับที่new Thread(() => {Some Work}).Start();ทำอยู่?! ไม่ใช่เหรอ
Roman Ratskey

2
ไม่ สมมติฐานของคุณไม่ถูกต้อง คุณอาจกำลังนึกถึงTask.Run (TPL) ซึ่งมักจะรวมกับ Async / Await แต่ก็ไม่เกี่ยวข้องกันและไม่จำเป็นต้องใช้กับมัน
dtb

4
@dtb: ควรใช้ Async / Await เมื่อใดและควรใช้ Threads เมื่อใด ฉันสับสนจริงๆเกี่ยวกับความแตกต่างระหว่าง Task.Run, Thread.Start, Async / Await หากคุณสามารถให้คำอธิบายที่ดีกับฉันที่ทำให้ฉันเข้าใจความแตกต่างระหว่างพวกเขาได้ฉันจะขอบคุณมาก
Roman Ratskey

2
Async / await ไม่ได้สร้างหรือใช้เธรดในทางอื่น
wRAR

คำตอบ:


83

สามารถแทนที่วิธีการใช้เธรดแบบเดิมได้อย่างสมบูรณ์หรือไม่?

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

สามารถทำสิ่งที่เคย Thread สามารถทำแบบอะซิงโครนัสได้หรือไม่?

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

ใช้ได้เฉพาะกับบางวิธีเช่น WebClientDownloadStringAsync

ไม่ได้คุณสามารถใช้กับวิธีใดก็ได้ที่ส่งคืนงาน วิธีการ XxxxAsync () เป็นเพียงวิธีการที่กำหนดไว้ล่วงหน้าในกรอบงาน. NET สำหรับการดำเนินการทั่วไปที่ต้องใช้เวลา เช่นเดียวกับการดาวน์โหลดข้อมูลจากเว็บเซิร์ฟเวอร์


4
ในแง่มุม C # สมัยใหม่แนวทางที่ดีที่สุดในการบรรลุ Async-Callbacks บน API ภายนอกคืออะไร?
bonCodigo

5
ครอบคลุมในย่อหน้าสุดท้ายให้ใช้งาน
Hans Passant

ฉันคาดหวังบางอย่างที่เธรดสามารถทำได้ซึ่งไม่สามารถทำได้ผ่านการเขียนโปรแกรม async เป็นตัวอย่าง
Saeed Neamati

1
คุณช่วยขยาย "เธรดสามารถทำประโยชน์ได้อีกมากมาย" ได้ไหม การทำความเข้าใจเธรดคุณลักษณะที่asyncไม่เหมาะสมจะเป็นประโยชน์สำหรับ
Benjohn

1
ควรค่าแก่การกล่าวถึงawait Task.Runสำหรับงานที่เชื่อมต่อกับ CPU ถ้าฉันเข้าใจอย่างถูกต้องบางครั้งก็อาจจะทำสิ่งที่คนอื่นสร้างเธรดหรือผู้ทำงานเบื้องหลังให้ทำ
ToolmakerSteve

16

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


นี่เป็นเหมือนแหล่งข้อมูลแรกที่ฉันได้อ่านเกี่ยวกับ Threads และ Async / Await ที่ชัดเจนและกระชับ
Arman Bimatov

2
คำตอบนี้มีลิงก์ไปยังเอกสารเท่านั้น เนื่องจากลิงก์อาจล้าสมัยคำตอบอาจล้าสมัยเช่นกันหรือแย่กว่านั้น - ไร้ประโยชน์โดยสิ้นเชิง เราขอแนะนำให้ผู้ใช้ Stack โพสต์ส่วนที่เกี่ยวข้องของลิงก์ลงในคำถามโดยตรงแทน
HimBromBeere

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

2

ฉันคิดแบบนี้ (และฉันคิดว่า Microsoft ก็ทำเช่นกันหากคุณดูที่https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/hh191443(v=vs.110 ) #threads )

Async / await เป็นวิธีที่รวดเร็วในการรันโค้ดบางส่วนบนเธรดแอปพลิเคชันหลักโดยมีข้อได้เปรียบที่โค้ดสามารถระงับตัวเองเมื่อไม่มีงานที่ต้องทำและกลับโฟกัสไปที่เธรดหลัก "ปลุก" บนเธรดหลักเมื่อมี คือผลลัพธ์ที่จะได้รับจากนั้นผ่านการประมวลผลกลับไป - คุณเดาได้ - เธรดหลัก คิดว่ามันเหมือนกับคำสั่ง GOTO ตามเหตุการณ์ในขั้นพื้นฐานที่สามารถส่งการควบคุมกลับไปกลับมาไปยังบรรทัดการดำเนินการเฉพาะ

ในทางตรงกันข้ามเธรดคือสตรีมการดำเนินการแยกต่างหากที่สามารถรันด้วยตัวแปรของตัวเองเป็นต้นโดยที่ - ให้ฮาร์ดแวร์เพียงพอ - การดำเนินการจะเกิดขึ้นพร้อมกันกับเธรดหลัก

หากคุณมีแอปพลิเคชั่น GUI ที่จะดาวน์โหลดไฟล์เดียวแล้วทำอะไรกับไฟล์นั้นเมื่อดาวน์โหลดมา - ฉันจะใช้มันโดยใช้วิธี async / await

อย่างไรก็ตามหาก GUI ของคุณต้องการดาวน์โหลด 5,000 ไฟล์ฉันจะสร้างเธรดดาวน์โหลดไฟล์เพื่อจัดการกับสิ่งนั้นเนื่องจากเธรด GUI หลักอาจหยุดทำงานในขณะที่การดำเนินการถูกโอนเพื่อจัดการกับการดาวน์โหลดไฟล์

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