private void RunAsync()
{
string param = "Hi";
Task.Run(() => MethodWithParameter(param));
}
private void MethodWithParameter(string param)
{
}
แก้ไข
เนื่องจากความต้องการที่เป็นที่นิยมฉันต้องทราบว่า Task
เปิดตัวจะทำงานควบคู่ไปกับเธรดการโทร สมมติว่าเริ่มต้นนี้จะใช้สุทธิTaskScheduler
ThreadPool
อย่างไรก็ตามนี่หมายความว่าคุณต้องคำนึงถึงพารามิเตอร์ใด ๆ ที่ส่งผ่านไปยังTask
เธรดหลายเธรดที่อาจเข้าถึงได้พร้อมกันทำให้เป็นสถานะที่ใช้ร่วมกัน ซึ่งรวมถึงการเข้าถึงบนเธรดการโทร
ในรหัสด้านบนของฉันกรณีนี้ถูกสร้างขึ้นทั้งหมด สตริงไม่เปลี่ยนรูป นั่นเป็นเหตุผลที่ฉันใช้เป็นตัวอย่าง แต่บอกว่าคุณไม่ได้ใช้String
...
ทางออกหนึ่งคือการใช้async
และawait
. โดยค่าเริ่มต้นจะจับSynchronizationContext
เธรดการโทรและจะสร้างความต่อเนื่องสำหรับส่วนที่เหลือของวิธีการหลังจากการโทรไปที่await
Task
และแนบไปกับที่สร้างขึ้น หากวิธีนี้ทำงานอยู่ใน WinForms GUI WindowsFormsSynchronizationContext
ที่ด้ายมันจะเป็นประเภท
ความต่อเนื่องจะทำงานหลังจากที่โพสต์กลับไปที่บันทึกSynchronizationContext
- อีกครั้งตามค่าเริ่มต้นเท่านั้น ดังนั้นคุณจะกลับมาที่เธรดที่คุณเริ่มต้นหลังจากการawait
โทร ConfigureAwait
คุณสามารถเปลี่ยนได้ในความหลากหลายของรูปแบบที่สะดุดตาใช้ ในระยะสั้นส่วนที่เหลือของวิธีการที่จะไม่ดำเนินต่อไปจนถึงหลังTask
ได้เสร็จสิ้นในหัวข้ออื่น แต่เธรดการเรียกจะยังคงทำงานแบบขนานไม่ใช่ส่วนที่เหลือของเมธอด
การรอเพื่อรันวิธีที่เหลือนี้ให้เสร็จสมบูรณ์อาจเป็นที่ต้องการหรือไม่ก็ได้ หากไม่มีสิ่งใดในวิธีการนั้นในภายหลังเข้าถึงพารามิเตอร์ที่ส่งไปยังTask
คุณอาจไม่ต้องการใช้await
เลย
หรือบางทีคุณอาจใช้พารามิเตอร์เหล่านั้นในภายหลังในวิธีการ ไม่มีเหตุผลที่จะawait
ทันทีที่คุณสามารถทำงานต่อไปได้อย่างปลอดภัย โปรดจำไว้ว่าคุณสามารถจัดเก็บสิ่งที่Task
ส่งคืนในตัวแปรและเก็บawait
ไว้ในภายหลังได้แม้จะใช้วิธีเดียวกันก็ตาม ตัวอย่างเช่นเมื่อคุณต้องการเข้าถึงพารามิเตอร์ที่ส่งผ่านอย่างปลอดภัยหลังจากทำงานอื่น ๆ อีกครั้งคุณไม่จำเป็นต้องawait
อยู่Task
ทางด้านขวาเมื่อคุณเรียกใช้
อย่างไรก็ตามวิธีง่ายๆในการทำให้เธรดนี้ปลอดภัยโดยคำนึงถึงพารามิเตอร์ที่ส่งไปให้Task.Run
คือการทำสิ่งนี้:
ก่อนอื่นคุณต้องตกแต่งRunAsync
ด้วยasync
:
private async void RunAsync()
โน๊ตสำคัญ
โดยเฉพาะอย่างยิ่งวิธีการที่ทำเครื่องหมายไว้ไม่ควรคืนค่าเป็นโมฆะตามที่เอกสารที่เชื่อมโยงกล่าวถึง ข้อยกเว้นทั่วไปสำหรับกรณีนี้คือตัวจัดการเหตุการณ์เช่นการคลิกปุ่มเป็นต้น พวกเขาจะต้องคืนความว่างเปล่า มิฉะนั้นฉันจะพยายามส่งคืนหรือasync
Task
Task<TResult>
async
เมื่อใช้ เป็นแนวทางปฏิบัติที่ดีด้วยเหตุผลบางประการ
ตอนนี้คุณสามารถawait
เรียกใช้สิ่งที่Task
คล้ายกันด้านล่าง คุณไม่สามารถใช้โดยไม่ต้องawait
async
await Task.Run(() => MethodWithParameter(param));
ดังนั้นโดยทั่วไปหากคุณawait
ทำงานคุณสามารถหลีกเลี่ยงการปฏิบัติต่อพารามิเตอร์ที่ส่งผ่านในฐานะทรัพยากรที่ใช้ร่วมกันได้โดยมีข้อผิดพลาดทั้งหมดของการแก้ไขบางสิ่งจากหลายเธรดพร้อมกัน นอกจากนี้ระวังของการปิด ฉันจะไม่พูดถึงสิ่งเหล่านั้นในเชิงลึก แต่บทความที่เชื่อมโยงนั้นทำได้ดีมาก
หมายเหตุด้านข้าง
นอกเรื่องเล็กน้อย แต่ระวังการใช้ "การบล็อก" ประเภทใด ๆ บนเธรด WinForms GUI เนื่องจากมีการทำเครื่องหมายด้วย [STAThread]
เพราะมันถูกทำเครื่องหมายด้วย การใช้await
จะไม่บล็อกเลย แต่บางครั้งฉันเห็นว่าใช้ร่วมกับการบล็อกบางประเภท
"บล็อก" อยู่ในเครื่องหมายคำพูดเนื่องจากในทางเทคนิคแล้วคุณไม่สามารถบล็อกเธรด WinForms GUIได้ ใช่ถ้าคุณใช้lock
กับเธรด WinForms GUI มันจะยังคงปั๊มข้อความแม้ว่าคุณจะคิดว่า "ถูกบล็อก" ก็ตาม มันไม่ใช่.
ซึ่งอาจทำให้เกิดปัญหาแปลกประหลาดในบางกรณีที่เกิดขึ้นได้ยาก เหตุผลประการหนึ่งที่คุณไม่ต้องการใช้lock
เมื่อวาดภาพเป็นต้น แต่นั่นเป็นกรณีที่ซับซ้อนและซับซ้อน อย่างไรก็ตามฉันเห็นว่ามันทำให้เกิดปัญหาที่บ้าคลั่ง ดังนั้นฉันจึงตั้งข้อสังเกตเพื่อความสมบูรณ์