iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >c# 在Emit代码中如何await一个异步方法
  • 556
分享到

c# 在Emit代码中如何await一个异步方法

2024-04-02 19:04:59 556人浏览 独家记忆
摘要

目录0. 前言Demo 说明1. ContinueWith2. GetAwaiter().GetResult()3. async/await完整Demo放在0. 前言 首先立马解释

0. 前言

首先立马解释一波为啥会有这样一篇伪标题的Demo随笔呢?
不是本人有知识误区,或者要误人子弟
因为大家都知道emit写出来的都是同步方法,不可能await,至少现在这么多年来没有提供对应的功能
这是之前某天在微信群看见讨论怎么emit一个异步方法并包装异步结构,简单几句文字也未能清晰的表达
所以趁着元旦节放假有点时间,
简单列举三种我知道方式去达到这样的效果
三种方法都是绕过emit直接书写emit代码,而是将对应逻辑转到其他方法中,最后emit调用方法达到效果

Demo 说明

原始方法是个延迟2秒之后返回55的方法:


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

现在我们需要把 55 的结果加 6 ,让最终的结果变为 61

我们的测试方法是这样,会输出一些简单的时间,帮助我们了解执行顺序和异步情况


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

1. ContinueWith


  public static Func<Task<int>> CreateCaller(MethodInfo method, MethodInfo awaitMehtod)
  {
   var m = new DynamicMethod(Guid.NewGuid().ToString("N"), typeof(Task<int>), Type.EmptyTypes);
   var il = m.GetILGenerator();
   il.Emit(OpCodes.Call, method);
   il.Emit(OpCodes.Call, typeof(Program).GetMethod(nameof(Program.AddSixUseContinueWith))); // 这里是差异点
   il.Emit(OpCodes.Ret);

   return m.CreateDelegate(typeof(Func<Task<int>>)) as Func<Task<int>>;
  }

  public static Task<int> AddSixUseContinueWith(Task<int> task)
  {
   return task.ContinueWith(i =>
   {
    Console.WriteLine($"AddSixUseContinueWith is: {DateTime.Now}.");
    return i.Result + 6;
   });
  }

测试结果:


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.

优点
还是真正的异步

缺点
成本比较大,毕竟这样没有了状态机等等优化,(成本在 ns 级别哦,不是大家想的 ms哦)

2. GetAwaiter().GetResult()


  public static Func<Task<int>> CreateCaller(MethodInfo method, MethodInfo awaitMehtod)
  {
   var m = new DynamicMethod(Guid.NewGuid().ToString("N"), typeof(Task<int>), Type.EmptyTypes);
   var il = m.GetILGenerator();
   il.Emit(OpCodes.Call, method);
   il.Emit(OpCodes.Call, typeof(Program).GetMethod(nameof(Program.AddSixUseAwaiter))); // 这里是差异点
   il.Emit(OpCodes.Ret);

   return m.CreateDelegate(typeof(Func<Task<int>>)) as Func<Task<int>>;
  }

  public static Task<int> AddSixUseAwaiter(Task<int> task)
  {
   var r = task.ConfigureAwait(false).GetAwaiter().GetResult() + 6;
   Console.WriteLine($"AddSixUseAwaiter is: {DateTime.Now}.");
   return Task.FromResult(r);
  }

测试结果:


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.

优点
执行时间上消耗很小

缺点
当然这样 异步都变成了同步,所以可能会在某些情况下我们操作不当的代码从而导致失去异步方法的优势

3. async/await


  public static Func<Task<int>> CreateCaller(MethodInfo method, MethodInfo awaitMehtod)
  {
   var m = new DynamicMethod(Guid.NewGuid().ToString("N"), typeof(Task<int>), Type.EmptyTypes);
   var il = m.GetILGenerator();
   il.Emit(OpCodes.Call, method);
   il.Emit(OpCodes.Call, typeof(Program).GetMethod(nameof(Program.AddSixUseAsyncAwait))); // 这里是差异点
   il.Emit(OpCodes.Ret);

   return m.CreateDelegate(typeof(Func<Task<int>>)) as Func<Task<int>>;
  }

  public static async Task<int> AddSixUseAsyncAwait(Task<int> task)
  {
   var r = await task;
   Console.WriteLine($"AddSixUseAsyncAwait is: {DateTime.Now}.");
   return r + 6;
  }

测试结果:


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.

优点
async / await 本身的优势都没有损失

缺点
原本想在 emit 中 对result的处理逻辑 必须迁移到 async / await 方法中,emit代码必须好好设计

完整Demo放在

https://GitHub.com/fs7744/grocery/blob/main/csharp/emit_await/EmitAwaitDemo/Program.cs

分享不易,如果能给予一点动力,不胜感激:关注一下本人的开源项目: Norns.Urd

以上就是C# 在Emit代码中如何await一个异步方法的详细内容,更多关于c# Emit代码await一个异步方法的资料请关注编程网其它相关文章!

--结束END--

本文标题: c# 在Emit代码中如何await一个异步方法

本文链接: https://www.lsjlt.com/news/122237.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • c# 在Emit代码中如何await一个异步方法
    目录0. 前言Demo 说明1. ContinueWith2. GetAwaiter().GetResult()3. async/await完整Demo放在0. 前言 首先立马解释...
    99+
    2024-04-02
  • C#中使用async和await实现异步Udp通讯的示例代码
    目录C/S架构客户端实现客户端主流程和实现客户端发送消息实现客户端监听消息实现服务器实现服务器主流程和实现服务器发送消息实现服务器监听消息实现总结在之前的C#版本中, 如果我们想要进...
    99+
    2024-04-02
  • 如何进行C++代码的异步编程?
    如何进行C++代码的异步编程?在软件开发领域,异步编程(Asynchronous Programming)成为了必备技能之一。它可以更好地平衡CPU密集型操作和IO密集型操作的性能,使程序代码并发或并行执行,进而提高了程序的响应速度和整体性...
    99+
    2023-11-02
    异步(Async) 异步编程步骤: 线程(Thread) 回调(Callback)
  • 微信小程序中如何使用Async-await方法异步请求变为同步请求方法
    这篇文章给大家分享的是有关微信小程序中如何使用Async-await方法异步请求变为同步请求方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。微信小程序中有些 Api 是异步的,...
    99+
    2024-04-02
  • 如何在C++项目中实现一个aligned_malloc方法
    这篇文章将为大家详细讲解有关如何在C++项目中实现一个aligned_malloc方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。malloc的默认行为int main(){&n...
    99+
    2023-06-07
  • 一步步了解如何在Gitee上提交代码
    在现代化的软件开发中,版本控制是必不可少的一项工作。Git是世界上最流行的分布式版本控制系统之一,而Gitee是一个非常受欢迎的Git代码托管和协作平台。在这篇文章中,我们将带您逐步了解如何在Gitee上提交代码。步骤1:注册Gitee账号...
    99+
    2023-10-22
  • php中如何异步调用方法
    php中异步调用方法的操作步骤在返回客户端的html代码中,嵌入ajax调用或者嵌入一个img标签,src指向要执行的耗时脚本。使用popen函数打开一个指向进程的管道,该进程由派生给定的command命令执行而产生。使用CURL,设置CU...
    99+
    2024-04-02
  • 如何在PHP代码中调用JavaScript方法?
    如何在PHP代码中调用JavaScript方法? 在网页开发中,经常需要让PHP与JavaScript进行交互,其中一种常见需求就是在PHP代码中调用JavaScript方法。通过调用...
    99+
    2024-03-04
    php调用js
  • 如何在Github上删除一个代码库
    Github是全球最大的开源代码托管平台,它为开发人员提供了一个共享和管理代码的平台。在Github上,开发人员可以创建自己的代码库,并与其他人共享和协作。但是,有时候我们需要删除一个代码库,不再维护它。那么,如何在Github上删除一个代...
    99+
    2023-10-22
  • 如何在Go和JavaScript中测试异步编程代码的正确性?
    在当今的软件开发中,异步编程已经成为了一个非常常见的技术。它可以帮助我们更好地处理并发请求、提升性能和响应速度等。但是,异步编程也带来了一些挑战,其中之一就是如何测试异步代码的正确性。在本文中,我们将会讨论在Go和JavaScript中如何...
    99+
    2023-09-26
    javascript 异步编程 http
  • 如何在C#中使用 CancellationToken 处理异步任务
    目录手动取消任务 定时取消任务 CancellationToken 注册回调 在 HttpClient 中使用 在 WebAPI中使用 在 .NET Core 中使用异步编程已经很普...
    99+
    2024-04-02
  • Promise和Generato中如何用同步方法写异步JavaScript
    这篇文章给大家介绍Promise和Generato中如何用同步方法写异步JavaScript,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。最近在写一个自己的网站的时候(可以观摩一下~C...
    99+
    2024-04-02
  • JavaScript中如何在一个循环中等待示例代码详解
    下面是如何使用for..of 循环来迭代一个数组并在循环内等待: const fun = (prop) => { return new Promise(resolve =&...
    99+
    2024-04-02
  • 如何用前端代码在浏览器中构建一个Tableau
    如何用前端代码在浏览器中构建一个Tableau,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。在Gartner最新的对商务智能软件的专业分析报告中,Tableau持续领跑。Mic...
    99+
    2023-06-19
  • 如何在C#中实现一个TextBox事件
    本篇文章为大家展示了如何在C#中实现一个TextBox事件,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。C# TextBox事件的效果预期一般情况下:◆当一个页面有TextBox以及Button的时...
    99+
    2023-06-17
  • C#中如何关联多个方法
    这篇文章主要为大家展示了“C#中如何关联多个方法”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C#中如何关联多个方法”这篇文章吧。C#语言还是比较常见的东西,这里我们主要介绍C#多个方法的关联,...
    99+
    2023-06-17
  • Java在方法中如何抛出异常
    这篇文章主要介绍了Java在方法中如何抛出异常的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java在方法中如何抛出异常文章都会有所收获,下面我们一起来看看吧。异常机制概述异常机制是指当程序出现错误后,程序如何...
    99+
    2023-06-17
  • 如何在PyQt5中使用QListView实现一个代码高亮功能
    今天就跟大家聊聊有关如何在PyQt5中使用QListView实现一个代码高亮功能,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。使用setCurrentIndex(int) 来设置if...
    99+
    2023-06-14
  • eclipse中如何测试一个方法
    在Eclipse中,有多种方法可以测试一个方法。以下是其中几种常见的方法: 使用JUnit进行单元测试:JUnit是一个广泛使用的...
    99+
    2023-10-22
    eclipse
  • 如何在Java中使用 g.fillRect 方法创建一个Rectangle
    要使用 g.fillRect 方法创建一个 Rectangle,首先需要创建一个 Graphics 对象,并将其传递给 g.fill...
    99+
    2023-09-27
    Java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作