ฉันจะรอให้void async
วิธีการทำงานให้เสร็จได้อย่างไร
ตัวอย่างเช่นฉันมีฟังก์ชั่นด้านล่าง:
async void LoadBlahBlah()
{
await blah();
...
}
ตอนนี้ฉันต้องการให้แน่ใจว่าทุกอย่างถูกโหลดก่อนดำเนินการต่อที่อื่น
ฉันจะรอให้void async
วิธีการทำงานให้เสร็จได้อย่างไร
ตัวอย่างเช่นฉันมีฟังก์ชั่นด้านล่าง:
async void LoadBlahBlah()
{
await blah();
...
}
ตอนนี้ฉันต้องการให้แน่ใจว่าทุกอย่างถูกโหลดก่อนดำเนินการต่อที่อื่น
คำตอบ:
วิธีที่ดีที่สุดคือการทำเครื่องหมายฟังก์ชั่นเฉพาะในกรณีที่มันเป็นไฟและลืมวิธีการถ้าคุณต้องการที่จะรอที่คุณควรจะทำเครื่องหมายว่าasync void
async Task
ในกรณีที่คุณยังต้องการรออยู่ให้ปิดแผ่นให้เหมือนกัน await Task.Run(() => blah())
await Task.Run(() => An_async_void_method_I_can_not_modify_now())
await Task.Run(() => blah())
กำลังทำให้เข้าใจผิด สิ่งนี้ไม่ได้รอฟังก์ชั่น async ให้เสร็จสมบูรณ์blah
แต่จะรอการสร้าง (เล็กน้อย) ของงานและทำต่อไปทันทีก่อนที่จะblah()
เสร็จสมบูรณ์
Thread.Sleep
ไม่ใช่ async คำถามนี้เกี่ยวกับการรอasync void
ฟังก์ชั่นพูดasync void blah() { Task.Delay(10000); }
หากคุณสามารถเปลี่ยนลายเซ็นของฟังก์ชั่นของคุณasync Task
แล้วคุณสามารถใช้รหัสที่แสดงที่นี่
ทางออกที่ดีที่สุดคือการใช้ async Task
ทางออกที่ดีที่สุดคือการใช้งานคุณควรหลีกเลี่ยงasync void
ด้วยเหตุผลหลายประการซึ่งหนึ่งในนั้นคือการเรียงความ
หากไม่สามารถทำการคืนค่าได้Task
(เช่นเป็นตัวจัดการเหตุการณ์) คุณสามารถใช้SemaphoreSlim
เพื่อให้สัญญาณวิธีการได้เมื่อกำลังจะออก ลองทำสิ่งนี้ในfinally
บล็อก
ทำ AutoResetEvent ให้เรียกใช้ฟังก์ชั่นจากนั้นรอ AutoResetEvent แล้วตั้งค่าภายใน async เป็นโมฆะเมื่อคุณทราบว่าเสร็จสิ้น
นอกจากนี้คุณยังสามารถรองานที่ส่งคืนจากโมฆะ async ของคุณ
คุณไม่จำเป็นต้องทำอะไรด้วยตนเองawait
คำหลักหยุดการทำงานของฟังก์ชันชั่วคราวจนกว่าจะblah()
ส่งคืน
private async void SomeFunction()
{
var x = await LoadBlahBlah(); <- Function is not paused
//rest of the code get's executed even if LoadBlahBlah() is still executing
}
private async Task<T> LoadBlahBlah()
{
await DoStuff(); <- function is paused
await DoMoreStuff();
}
T
เป็นชนิดของการblah()
ส่งคืนวัตถุ
คุณไม่สามารถawait
ใช้void
งานฟังก์ชันLoadBlahBlah()
ได้void
LoadBlahBlah()
จนจบไม่ใช่blah()
ฉันรู้ว่านี่เป็นคำถามเก่า แต่ยังคงเป็นปัญหาที่ฉันยังคงเดินต่อไปและยังไม่มีวิธีแก้ปัญหาที่ชัดเจนในการทำอย่างถูกต้องเมื่อใช้ async / รอในวิธีการเซ็นชื่อเป็นโมฆะ async
อย่างไรก็ตามฉันสังเกตเห็นว่า. Wait () ทำงานอย่างถูกต้องภายในวิธี void
และเนื่องจาก async เป็นโมฆะและโมฆะมีลายเซ็นเดียวกันคุณอาจต้องทำดังต่อไปนี้
void LoadBlahBlah()
{
blah().Wait(); //this blocks
}
async / await ที่สับสนพอไม่ได้บล็อคในโค้ดถัดไป
async void LoadBlahBlah()
{
await blah(); //this does not block
}
เมื่อคุณถอดรหัสโค้ดของฉันฉันเดาว่า async void จะสร้างงานภายใน (เช่นเดียวกับ async Task) แต่เนื่องจากลายเซ็นไม่รองรับการส่งคืนงานภายในนั้น
ซึ่งหมายความว่าวิธีการโมฆะ async ภายในจะยังสามารถ "รอ" วิธีการซิงค์ภายใน แต่ภายนอกไม่สามารถรู้ได้เมื่องานภายในเสร็จสมบูรณ์
ดังนั้นข้อสรุปของฉันคือโมฆะ async ทำงานได้ตามที่ตั้งใจและถ้าคุณต้องการข้อเสนอแนะจากงานภายในแล้วคุณต้องใช้ลายเซ็นงาน async แทน
หวังว่าการเที่ยวของฉันจะสมเหตุสมผลกับทุกคนที่กำลังมองหาคำตอบด้วย
แก้ไข: ฉันสร้างโค้ดตัวอย่างและถอดรหัสเพื่อดูว่าเกิดอะไรขึ้นจริง
static async void Test()
{
await Task.Delay(5000);
}
static async Task TestAsync()
{
await Task.Delay(5000);
}
เปลี่ยนเป็น (แก้ไข: ฉันรู้ว่ารหัสร่างกายไม่ได้อยู่ที่นี่ แต่ใน statemachines แต่ statemachines เหมือนกันโดยทั่วไปดังนั้นฉันจึงไม่ต้องกังวลเพิ่ม)
private static void Test()
{
<Test>d__1 stateMachine = new <Test>d__1();
stateMachine.<>t__builder = AsyncVoidMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncVoidMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
}
private static Task TestAsync()
{
<TestAsync>d__2 stateMachine = new <TestAsync>d__2();
stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
stateMachine.<>1__state = -1;
AsyncTaskMethodBuilder <>t__builder = stateMachine.<>t__builder;
<>t__builder.Start(ref stateMachine);
return stateMachine.<>t__builder.Task;
}
ทั้ง AsyncVoidMethodBuilder หรือ AsyncTaskMethodBuilder จะมีรหัสใด ๆ ในวิธีการเริ่มต้นที่จะบอกใบ้ให้พวกเขาบล็อกและจะทำงานแบบอะซิงโครนัสเสมอหลังจากที่เริ่มต้นแล้ว
ความหมายหากไม่มีภารกิจที่ส่งคืนจะไม่มีวิธีตรวจสอบว่ามันสมบูรณ์หรือไม่
อย่างที่คาดไว้มันจะเริ่มงานที่กำลังทำงาน async เท่านั้นและจากนั้นจะดำเนินการต่อในรหัส และ async Task อันดับแรกมันจะเริ่ม Task จากนั้นก็คืนค่ามัน
ดังนั้นฉันเดาว่าคำตอบของฉันจะไม่ใช้ async เป็นโมฆะถ้าคุณจำเป็นต้องรู้เมื่องานเสร็จนั่นคือสิ่งที่ async Task ใช้