อาจจะสายเกินไป แต่อาจมีประโยชน์ในการตรวจสอบ:
มีโครงสร้างภายในของโค้ดที่คอมไพล์ ( IL ):
public static async Task<int> GetTestData()
{
return 12;
}
กลายเป็นใน IL:
.method private hidebysig static class [mscorlib]System.Threading.Tasks.Task`1<int32>
GetTestData() cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.AsyncStateMachineAttribute::.ctor(class [mscorlib]System.Type) = ( 01 00 28 55 73 61 67 65 4C 69 62 72 61 72 79 2E
53 74 61 72 74 54 79 70 65 2B 3C 47 65 74 54 65
73 74 44 61 74 61 3E 64 5F 5F 31 00 00 )
.custom instance void [mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor() = ( 01 00 00 00 )
.maxstack 2
.locals init ([0] class UsageLibrary.StartType/'<GetTestData>d__1' V_0,
[1] valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> V_1)
IL_0000: newobj instance void UsageLibrary.StartType/'<GetTestData>d__1'::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: call valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<!0> valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::Create()
IL_000c: stfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> UsageLibrary.StartType/'<GetTestData>d__1'::'<>t__builder'
IL_0011: ldloc.0
IL_0012: ldc.i4.m1
IL_0013: stfld int32 UsageLibrary.StartType/'<GetTestData>d__1'::'<>1__state'
IL_0018: ldloc.0
IL_0019: ldfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> UsageLibrary.StartType/'<GetTestData>d__1'::'<>t__builder'
IL_001e: stloc.1
IL_001f: ldloca.s V_1
IL_0021: ldloca.s V_0
IL_0023: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::Start<class UsageLibrary.StartType/'<GetTestData>d__1'>(!!0&)
IL_0028: ldloc.0
IL_0029: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> UsageLibrary.StartType/'<GetTestData>d__1'::'<>t__builder'
IL_002e: call instance class [mscorlib]System.Threading.Tasks.Task`1<!0> valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::get_Task()
IL_0033: ret
}
และไม่มี async และวิธีการงาน:
public static int GetTestData()
{
return 12;
}
กลายเป็น :
.method private hidebysig static int32 GetTestData() cil managed
{
.maxstack 1
.locals init ([0] int32 V_0)
IL_0000: nop
IL_0001: ldc.i4.s 12
IL_0003: stloc.0
IL_0004: br.s IL_0006
IL_0006: ldloc.0
IL_0007: ret
}
อย่างที่คุณเห็นความแตกต่างใหญ่ระหว่างวิธีการเหล่านี้ หากคุณไม่ใช้ await ภายในวิธี async และไม่สนใจเกี่ยวกับการใช้วิธี async (เช่นการเรียก API หรือตัวจัดการเหตุการณ์) แนวคิดที่ดีจะแปลงเป็นวิธีการซิงค์ปกติ (ช่วยประหยัดประสิทธิภาพแอปพลิเคชันของคุณ)
อัปเดต:
นอกจากนี้ยังมีข้อมูลเพิ่มเติมจาก microsoft docs https://docs.microsoft.com/en-us/dotnet/standard/async-in-depth :
วิธีการ async จำเป็นต้องมีคีย์เวิร์ดรออยู่ในตัวไม่เช่นนั้นจะไม่มีวันยอม! นี่เป็นสิ่งสำคัญที่ต้องจำไว้ หากไม่ได้ใช้ await ในเนื้อความของวิธีการ async คอมไพลเลอร์ C # จะสร้างคำเตือน แต่โค้ดจะคอมไพล์และรันเหมือนเป็นวิธีการปกติ โปรดทราบว่าสิ่งนี้จะไม่มีประสิทธิภาพอย่างไม่น่าเชื่อเนื่องจากเครื่องสถานะที่สร้างโดยคอมไพเลอร์ C # สำหรับวิธี async จะไม่สามารถทำอะไรได้เลย
async
?