C#使用多线程并发之异步委托

2023-11-02

阻塞式编程:我们一边编写的代码都是同步代码,也就是从上到下按照顺序执行。

例如

public delegate void DoWorkHandler();

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始烧水了");

            // 一直等到水烧开
            DoWorkHandler handler = (() =>
                {
                    Thread.Sleep(2000);
                    Console.WriteLine("水烧好了");
                });
            handler.Invoke();

            // 在水未烧开之前一直会有阻塞
            Console.WriteLine("扫一下地吧");
        }
    }

或者这样形式

 public delegate int DoWorkHandler(int ms);

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("程序开始");

            // 一直等到水烧开
            DoWorkHandler handler = BoilWaterHandler;

            IAsyncResult asyncResult = handler.BeginInvoke(2000, null, null);
            //EndInvoke方法将被阻塞2秒。一直等待委托完成其任务为止
            int result = handler.EndInvoke(asyncResult);

            Console.WriteLine(result);
            Console.WriteLine("扫一下地吧");
            Console.ReadKey();

        }

        static int BoilWaterHandler(int ms)
        {
            Console.WriteLine("开始烧水");
            Thread.Sleep(ms);
            Console.WriteLine("烧水完成");
            return ++ms;
        }
     }

都是要阻塞2秒。怎样防止程序被阻塞,让CPU继续执行其他任务呢?

为了解决以上问题,我们需要使用异步的方式编程,原理其实就是遇到耗时较多的任务时,操作系统实现了时间片轮转调度算法,切换到另一个线程。

方案1、用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程,使用IAsyncResult.IsCompleted属性来判断异步调用是否完成。在C#中,Delegate类包含Invoke和BeginInvoke两个方法,其中Invoke是同步的,而BeginInvoke则是异步的

  public delegate void DoWorkHandler();

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始烧水了");

            // 一直等到水烧开
            DoWorkHandler handler = (() =>
            {
                Thread.Sleep(5000);
                Console.WriteLine("水烧好了");
            });

            // 这里不会有阻塞,我们可以做一些其他事情
            IAsyncResult asyncResult = handler.BeginInvoke(null, null);
            while (!asyncResult.IsCompleted)
            {
                Console.WriteLine("水还没烧好,先干点其的他事情吧");
                Thread.Sleep(1000);
            }

            Console.WriteLine("扫一下地吧");
            Console.ReadKey();

        }
      }

方案2、使用回调方式返回结果

第一种写法

 public delegate void DoWorkHandler();

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始烧水了");

            // 一直等到水烧开
            DoWorkHandler handler = (() =>
            {
                Thread.Sleep(5000);
                Console.WriteLine("水烧好了");
            });


            // 异步回调
            IAsyncResult asyncResult = handler.BeginInvoke(new AsyncCallback(CallBack), null);
            while (!asyncResult.IsCompleted)
            {
                Console.WriteLine("水还没烧好,先干点其的他事情吧");
                Thread.Sleep(1000);
            }

            Console.WriteLine("扫一下地吧");
            Console.ReadKey();

        }

        static void CallBack(IAsyncResult result)
        {
            DoWorkHandler handler = (result as AsyncResult).AsyncDelegate as DoWorkHandler;
            handler.EndInvoke(result);
        }

 

 第二种写法

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 异步编程测试
{
    public delegate int DoWorkHandler(int ms);

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("开始烧水了");

            // 一直等到水烧开
            DoWorkHandler handler = DoHeatWater;


            handler.BeginInvoke(3000, CallBack, handler);


            Console.WriteLine("扫一下地吧");
            Console.ReadKey();

        }

        static int DoHeatWater(int ms)
        {
            Thread.Sleep(ms);
            Console.WriteLine("水烧好了");
            return ++ms;
        }

        static void CallBack(IAsyncResult result)
        {
            if (result == null)
            {
                throw new ArgumentNullException("result");
            }
            DoWorkHandler handler = result.AsyncState as DoWorkHandler;
            Trace.Assert(handler != null, "invalid objevt type");
            int data = handler.EndInvoke(result);
            Console.WriteLine(data);
        }

    }

}

参考:

https://blog.csdn.net/qq_34057374/article/details/76460578

https://blog.csdn.net/HerryDong/article/details/82825548

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#使用多线程并发之异步委托 的相关文章

  • 以文化中立的方式将字符串拆分为单词

    我提出了下面的方法 旨在将可变长度的文本拆分为单词数组 以进行进一步的全文索引处理 删除停止词 然后进行词干分析 结果似乎不错 但我想听听关于这种实现对于不同语言的文本的可靠性的意见 您会建议使用正则表达式来代替吗 请注意 我选择不使用 S
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • Web 客户端和 Expect100Continue

    使用 WebClient C NET 时设置 Expect100Continue 的最佳方法是什么 我有下面的代码 我仍然在标题中看到 100 continue 愚蠢的 apache 仍然抱怨 505 错误 string url http
  • 为什么当实例化新的游戏对象时,它没有向它们添加标签? [复制]

    这个问题在这里已经有答案了 using System Collections using System Collections Generic using UnityEngine public class Test MonoBehaviou
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • BitTorrent 追踪器宣布问题

    我花了一点业余时间编写 BitTorrent 客户端 主要是出于好奇 但部分是出于提高我的 C 技能的愿望 我一直在使用理论维基 http wiki theory org BitTorrentSpecification作为我的向导 我已经建
  • 在 Windows 窗体中保存带有 Alpha 通道的单色位图会保存不同(错误)的颜色

    在 C NET 2 0 Windows 窗体 Visual Studio Express 2010 中 我保存由相同颜色组成的图像 Bitmap bitmap new Bitmap width height PixelFormat Form
  • 如何从 appsettings.json 文件中的对象数组读取值

    我的 appsettings json 文件 StudentBirthdays Anne 01 11 2000 Peter 29 07 2001 Jane 15 10 2001 John Not Mentioned 我有一个单独的配置类 p
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 控件的命名约定[重复]

    这个问题在这里已经有答案了 Microsoft 在其网站上提供了命名指南 here http msdn microsoft com en us library xzf533w0 VS 71 aspx 我还有 框架设计指南 一书 我找不到有关
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 如何在Xamarin中删除ViewTreeObserver?

    假设我需要获取并设置视图的高度 在 Android 中 众所周知 只有在绘制视图之后才能获取视图高度 如果您使用 Java 有很多答案 最著名的方法之一如下 取自这个答案 https stackoverflow com a 24035591
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • C++ 中类级 new 删除运算符的线程安全

    我在我的一门课程中重新实现了新 删除运算符 现在我正在使我的代码成为多线程 并想了解这些运算符是否也需要线程安全 我在某处读到 Visual Studio 中默认的 new delete 运算符是线程安全的 但这对于我的类的自定义 new
  • 对来自流读取器的过滤数据执行小计

    编辑问题未得到解答 我有一个基于 1 个标准的过滤输出 前 3 个数字是 110 210 或 310 给出 3 个不同的组 从流阅读器控制台 问题已编辑 因为第一个答案是我给出的具体示例的字面解决方案 我使用的实际字符串长度为 450 个

随机推荐

  • layout_gravity不能居中以及失效、无法使用问题的解决办法

    layout gravity不能居中以及失效 无法使用问题的解决办法 今天在工作中遇到了关于layout gravity属性失效的问题 在查阅了相关资料后 了解到了一些解决的办法 顺便写一篇文章记录一下 首先 先了解一下layout gra
  • 微服务开发的意义 微服务与分布式的关系

    意义 将单体应用拆分为一组小服务 协同工作 小而自治 每个服务在独立的进程运行 服务之间使用轻量级的通信机制RPC 单一职责 一个微服务解决一个业务问题 注意是一个业务问题而不是一个接口 服务围绕业务构建 服务可以独立部署 低耦合 面向服务
  • debian 文件夹中文件大小_Debian基本设置笔记

    易用的东西 不用看说明 上手就可以直接用起来 正常的东西 需要搜说明 搜个两三次 也就记住了 而类似设置Linux这种东西 每次用 都要每次重新搜来搜去 试来试去 本科的时候 在一位来自衡中的同学指导下 安装了一个Debian with x
  • ajax和mybatis,Springboot+Ajax+Mybatis+Mysql实现异步登录

    本人大学生 搞了三年的 PHP 感觉 PHP 的生态还是不行 但是 PHP 仍然是全世界最好的语言 上手简单 能快速搭建起一个项目 由于快要找工作了想花一年的时间来搞搞 Java 搞了一段时间后发现 Java 整套是真是完善 可扩展性很强
  • 关于benchmark的Instruction Cache Misses测试

    指令高速缓存未命中与数据高速缓存未命中相似 都是由于高速缓存已满而造成其它指令被冲出 也被称为capacity misses 为了测试指令的cache misses和memory相关信息 一般可使用perf工具或 Intel VTune 关
  • 使用Airtest IDE进行web自动化测试

    最近在使用selenium进行web自动化测试脚本的编写 但是定位很麻烦 编写耗时耗力 于是便在网上寻找有没有类似的测试工具 经过一段时间的寻找 终于找到一款网易开发的开源自动化测试工具 Airtest IDE 官网地址 Airtest P
  • IT行业接项目的方法总结(接私活可用)

    首先了解下众包和外包的区别 外包 外包是将项目承包给外包公司 由外包公司的程序员进行开发 众包 众包是将项目承包给多个独立的开发者 他们不隶属于任何公司 用自己的业余时间接私活 进行开发 接单的方法 朋友介绍 如果自己工作的时间长 熟悉软件
  • Double Machine Learning

    1 从线性回归说起 从观测数据获得因果效应的一个简单方式是使用线性回归 控制confounders的影响 S a l e s i
  • kafka+java工具类_Kafka工具类(Scala)

    1 配置文件config properties Kafka配置 kafka broker list hadoop300 9092 hadoop301 9092 hadoop302 9092 Redis配置 redis host hadoop
  • 用QT实现同步调用WebService

    QT提供了QNetworkAccessManager来访问 QT帮助文档里有这么一段 QNetworkAccessManager manager new QNetworkAccessManager this connect manager
  • Atlas200

    Atlas200 https bbs huaweicloud com forum thread 22913 1 1 html https ascend huawei com documentation details zh v1 1 1 1
  • 在Vue中实现全屏背景图片

    background url xx images 图片名字 jpg 这里的地址是用你项目中图片所在的路径为准 background repeat no repeat 将图片样式不重复 background size 100 100 设置图片
  • Unity简易实现角色脚下光圈

    方案一 使用Projector投影 最终效果 准备工作 1 一张背景为透明的圆圈图案 我这里是从阿里巴巴矢量网搜索圆圈下载到的 2 Standard Assets资源包 去AssetStore下载通用资源包 需要用到里面的light sha
  • 分治策略时间复杂度分析(一)-用代入法求解递归式

    分治策略时间复杂度分析 一 用代入法求解递归式 分治策略是算法中的一种重要的思想 比如归并排序就是用到了分治的策略 在分治策略中我们递归地求解一个问题 在每一层递归中都应用三个步骤 1 分解 2 解决 3 合并 文章目录 分治策略时间复杂度
  • Qt Creator创建项目后报错‘./ui_xx.h‘ file not found

    错误提示如图 错误原因 创建项目时勾选了形成xx ui文件 此ui文件在构建项目后产生 故在没有构建项目前报错属于正常 解决办法 构建项目后关闭再重新打开文件 提示即消失
  • 2023年江西省赣州市技能大赛 网络安全竞赛试题任务书

    2023年江西省赣州市技能大赛 网络安全竞赛试题任务书 A模块基础设施设置 安全加固 200分 A 1任务一 登录安全加固 A 2任务二 本地安全策略设置 A 3任务三 流量完整性保护 A 4任务四 事件监控 A 5任务五 服务加固 B模块
  • Vmware16 下载与安装

    Vmware16 下载与安装 vmware16 密钥 ZF3R0 FHED2 M80TY 8QYGC NPKYF YF390 0HF8P M81RQ 2DXQE M2UT6 ZF71R DMX85 08DQY 8YMNC PPHV8 Vmw
  • tshark解析本地pcap数据包提取五元组{src_ip,src_port,proto,dst_ip,dst_port}与时间戳,包长

    tshark官方文档 https www wireshark org docs man pages tshark html wireshark官方特征参考 https www wireshark org docs dfref 前提需要安装w
  • 利用递归求斐波那契数列

    斐波那契额是二级递推数列 从第三项起 每项为前两项的和 利用函数的递归可以很好实现 只需每次返回n 1 和 n 2 即可 上代码 define CRT SECURE NO WARNINGS 1 include
  • C#使用多线程并发之异步委托

    阻塞式编程 我们一边编写的代码都是同步代码 也就是从上到下按照顺序执行 例如 public delegate void DoWorkHandler class Program static void Main string args Con