Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asynchronous programming with reflection

How can I create an asynchronous method using reflection?

Basically I need something like this:

async public Task asyncmethod()
{
   await something();
}

but I need to do it with reflection.

like image 993
mertin Avatar asked Feb 21 '23 03:02

mertin


2 Answers

The translation of async methods works at the level of the C# (or VB.NET) compiler, there is no support for it in CIL. What the compiler does in the simplest case is that it translates code like this:

async public Task asyncmethod()
{
    // some code
    var x = await something();
    // more code
}

into code that is basically equivalent to something like:

public Task asyncmethod()
{
   // some code
   return something().ContinueWith(
       t =>
       {
           var x = t.Result;
           // more code
       });
}

The real code is much more complicated that that (it uses SynchronizationContext, it's not actually asynchronous if something() returns already finished Task, it supports awaiting things other thank Tasks) and it would be even more complicated for more complicated C# code.

But if you really want to create async methods using Reflection.Emit, this transformation is what you actually have to do manually.

But one thing to note is that if your method uses await only once right before it returns, you can rewrite it into (assuming something() returns a Task and not something else that is awaitable):

public Task asyncmethod()
{
    // some code
    return something();
}
like image 188
svick Avatar answered Feb 22 '23 19:02

svick


The other way to parse your question is that you need to use reflection within the method (for instance, to access a private method), but still want to use await.

If that's the case, you can just use reflection like you normally would, get the Task (or whatever awaitable thing) back, then await it separately.

Something like:

public async Task asyncmethod()
{
    Task t = ... // code that fetches the Task via reflection
    await t;
}

although, as svick mentions, if the only await is at the end, just return the Task instead of marking the method async and using await.

like image 34
James Manning Avatar answered Feb 22 '23 17:02

James Manning