SoFunction
Updated on 2025-03-07

c# How to await an asynchronous method in Emit code

0. Preface

First, let me explain immediately why there is such a fake title demo essay?
It's not that I have misunderstandings about knowledge or that I want to mislead my children
Because everyone knows that all the emit writes are synchronization methods, it is impossible to await. At least there has been no corresponding function for so many years.
This was a discussion in a WeChat group one day before. How to emit an asynchronous method and package an asynchronous structure. A few simple words could not be clearly expressed
So take advantage of the New Year's Day holiday to have some time.
A brief list of three ways I know to achieve this effect
The three methods are to bypass emit and write the emit code directly, but instead transfer the corresponding logic to other methods, and finally, the emit method is called to achieve the effect.

Demo Instructions

The original method is a method that returns 55 after a delay of 2 seconds:

  public static async Task<int> GetV()
  {
   await (2000);
   return 55;
  }

Now we need to add 6 to the result of 55 to make the final result 61

Our test method is like this, which outputs some simple time to help us understand the execution order and asynchronous situation

  private static async Task Test(MethodInfo method, MethodInfo awaitMehtod)
  {
   var caller = CreateCaller(method, awaitMehtod);
   ($"Start {} at: {}.");
   var task = caller();
   ($"Call done at: {}.");
   var number = await task;
   ($"Hello {number} at: {}.");
   ($"End at: {}.");
   ();
  }

1. ContinueWith

  public static Func&lt;Task&lt;int&gt;&gt; CreateCaller(MethodInfo method, MethodInfo awaitMehtod)
  {
   var m = new DynamicMethod(().ToString("N"), typeof(Task&lt;int&gt;), );
   var il = ();
   (, method);
   (, typeof(Program).GetMethod(nameof())); // Here is the difference point   ();

   return (typeof(Func&lt;Task&lt;int&gt;&gt;)) as Func&lt;Task&lt;int&gt;&gt;;
  }

  public static Task&lt;int&gt; AddSixUseContinueWith(Task&lt;int&gt; task)
  {
   return (i =&gt;
   {
    ($"AddSixUseContinueWith is: {}.");
    return  + 6;
   });
  }

Test results:

Start AddSixUseContinueWith at: 2021/1/2 13:34:55.
Call done at: 2021/1/2 13:34:55.
AddSixUseContinueWith is: 2021/1/2 13:34:57.
Hello 61 at: 2021/1/2 13:34:57.
End at: 2021/1/2 13:34:57.

advantage
Really asynchronous

shortcoming
The cost is relatively high, after all, there is no optimization of state machines and other state machines (the cost is at the ns level, not what everyone thinks of ms)

2. GetAwaiter().GetResult()

  public static Func&lt;Task&lt;int&gt;&gt; CreateCaller(MethodInfo method, MethodInfo awaitMehtod)
  {
   var m = new DynamicMethod(().ToString("N"), typeof(Task&lt;int&gt;), );
   var il = ();
   (, method);
   (, typeof(Program).GetMethod(nameof())); // Here is the difference point   ();

   return (typeof(Func&lt;Task&lt;int&gt;&gt;)) as Func&lt;Task&lt;int&gt;&gt;;
  }

  public static Task&lt;int&gt; AddSixUseAwaiter(Task&lt;int&gt; task)
  {
   var r = (false).GetAwaiter().GetResult() + 6;
   ($"AddSixUseAwaiter is: {}.");
   return (r);
  }

Test results:

Start AddSixUseAwaiter at: 2021/1/2 13:34:57.
AddSixUseAwaiter is: 2021/1/2 13:34:59.
Call done at: 2021/1/2 13:34:59.
Hello 61 at: 2021/1/2 13:34:59.
End at: 2021/1/2 13:34:59.

advantage
Very little execution time

shortcoming
Of course, asynchronous becomes synchronous, so in some cases we may operate the code improperly, resulting in the loss of the advantages of the asynchronous method.

3. async/await

  public static Func&lt;Task&lt;int&gt;&gt; CreateCaller(MethodInfo method, MethodInfo awaitMehtod)
  {
   var m = new DynamicMethod(().ToString("N"), typeof(Task&lt;int&gt;), );
   var il = ();
   (, method);
   (, typeof(Program).GetMethod(nameof())); // Here is the difference point   ();

   return (typeof(Func&lt;Task&lt;int&gt;&gt;)) as Func&lt;Task&lt;int&gt;&gt;;
  }

  public static async Task&lt;int&gt; AddSixUseAsyncAwait(Task&lt;int&gt; task)
  {
   var r = await task;
   ($"AddSixUseAsyncAwait is: {}.");
   return r + 6;
  }

Test results:

Start AddSixUseAsyncAwait at: 2021/1/2 13:34:59.
Call done at: 2021/1/2 13:34:59.
AddSixUseAsyncAwait is: 2021/1/2 13:35:01.
Hello 61 at: 2021/1/2 13:35:01.
End at: 2021/1/2 13:35:01.

advantage
Async/await itself has no loss of advantages

shortcoming
The processing logic of the result in emit must be moved to the async/await method, and the emit code must be well designed.

The complete demo is placed

/fs7744/grocery/blob/main/csharp/emit_await/EmitAwaitDemo/

Sharing is not easy, if you can give me some motivation, I am very grateful: Pay attention to my open source project:

The above is the detailed content of how to await an asynchronous method in c# Emit code. For more information about c# Emit code await an asynchronous method, please pay attention to my other related articles!