Should I worry about “This async method lacks 'await' operators and will run synchronously” warning

后端 未结 5 1122
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-30 01:18

I have a interface which exposes some async methods. More specifically it has methods defined which return either Task or Task. I am using the async/await keywords.

5条回答
  •  爱一瞬间的悲伤
    2020-11-30 01:23

    It might be too late but it might be useful investigation:

    There is about inner structure of compiled code (IL):

     public static async Task GetTestData()
        {
            return 12;
        }
    

    it becomes to in IL:

    .method private hidebysig static class [mscorlib]System.Threading.Tasks.Task`1 
            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   // ..(UsageLibrary.
                                                                                                                                         53 74 61 72 74 54 79 70 65 2B 3C 47 65 74 54 65   // StartType+d__1..
      .custom instance void [mscorlib]System.Diagnostics.DebuggerStepThroughAttribute::.ctor() = ( 01 00 00 00 ) 
      // Code size       52 (0x34)
      .maxstack  2
      .locals init ([0] class UsageLibrary.StartType/'d__1' V_0,
               [1] valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 V_1)
      IL_0000:  newobj     instance void UsageLibrary.StartType/'d__1'::.ctor()
      IL_0005:  stloc.0
      IL_0006:  ldloc.0
      IL_0007:  call       valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::Create()
      IL_000c:  stfld      valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 UsageLibrary.StartType/'d__1'::'<>t__builder'
      IL_0011:  ldloc.0
      IL_0012:  ldc.i4.m1
      IL_0013:  stfld      int32 UsageLibrary.StartType/'d__1'::'<>1__state'
      IL_0018:  ldloc.0
      IL_0019:  ldfld      valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 UsageLibrary.StartType/'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::Startd__1'>(!!0&)
      IL_0028:  ldloc.0
      IL_0029:  ldflda     valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1 UsageLibrary.StartType/'d__1'::'<>t__builder'
      IL_002e:  call       instance class [mscorlib]System.Threading.Tasks.Task`1 valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1::get_Task()
      IL_0033:  ret
    } // end of method StartType::GetTestData
    

    And without async and task method:

     public static int GetTestData()
            {
                return 12;
            }
    

    becomes :

    .method private hidebysig static int32  GetTestData() cil managed
    {
      // Code size       8 (0x8)
      .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
    } // end of method StartType::GetTestData
    

    As you could see the big difference between these methods. If you don't use await inside async method and do not care about using of async method (for example API call or event handler) the good idea will convert it to normal sync method (it saves your application performance).

    Updated:

    There is also additional information from microsoft docs https://docs.microsoft.com/en-us/dotnet/standard/async-in-depth:

    async methods need to have an await keyword in their body or they will never yield! This is important to keep in mind. If await is not used in the body of an async method, the C# compiler will generate a warning, but the code will compile and run as if it were a normal method. Note that this would also be incredibly inefficient, as the state machine generated by the C# compiler for the async method would not be accomplishing anything.

提交回复
热议问题