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