Có thể đã quá muộn nhưng nó có thể là một cuộc điều tra hữu ích:
Có về cấu trúc bên trong của mã đã biên dịch ( IL ):
public static async Task<int> GetTestData()
{
return 12;
}
nó trở thành trong 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
}
Và không có phương thức không đồng bộ và tác vụ:
public static int GetTestData()
{
return 12;
}
trở thành:
.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
}
Như bạn có thể thấy sự khác biệt lớn giữa các phương pháp này. Nếu bạn không sử dụng phương thức await bên trong async và không quan tâm đến việc sử dụng phương thức async (ví dụ: lệnh gọi API hoặc trình xử lý sự kiện), thì ý kiến hay là chuyển nó sang phương thức đồng bộ thông thường (nó tiết kiệm hiệu suất ứng dụng của bạn).
Đã cập nhật:
Ngoài ra còn có thông tin bổ sung từ tài liệu microsoft https://docs.microsoft.com/en-us/dotnet/standard/async-in-depth :
các phương thức async cần phải có một từ khóa đang chờ trong nội dung của chúng nếu không chúng sẽ không bao giờ mang lại kết quả! Đây là điều quan trọng cần ghi nhớ. Nếu await không được sử dụng trong phần thân của một phương thức không đồng bộ, trình biên dịch C # sẽ tạo ra một cảnh báo, nhưng mã sẽ biên dịch và chạy như thể nó là một phương thức bình thường. Lưu ý rằng điều này cũng sẽ cực kỳ kém hiệu quả, vì máy trạng thái được tạo bởi trình biên dịch C # cho phương thức không đồng bộ sẽ không hoàn thành bất cứ điều gì.
async
?