当前位置: 首页 > article >正文

C# 的异步任务中, 如何暂停, 继续,停止任务

namespace taskTest
{using System;using System.Threading;using System.Threading.Tasks;public class MyService{private Task? workTask;private readonly SemaphoreSlim semaphore = new SemaphoreSlim(0, 1); // 初始为 0,Start() 启动时手动放行private readonly CancellationTokenSource cts = new CancellationTokenSource();private volatile bool autoReleaseSemaphore = true; // 控制 ProcessAsync 是否自动 Releasepublic void Start(){Console.WriteLine("Starting service");autoReleaseSemaphore = true;semaphore.Release(); // 初始启动一次workTask = Task.Run(() => TreadJob(cts.Token));Console.WriteLine("Service started, task ID: " + workTask.Id);}public void Pause(){Console.WriteLine("Pausing service...");autoReleaseSemaphore = false; // 禁止 ProcessAsync 自动 Release}public void Resume(){Console.WriteLine("Resuming service...");autoReleaseSemaphore = true; // 允许 ProcessAsync 自动 Releasesemaphore.Release(); // 手动触发一次 Release,唤醒阻塞的 WaitAsync}public void Stop(){Console.WriteLine("Stopping service...");cts.Cancel();}private async Task TreadJob(CancellationToken token){Console.WriteLine("TreadJob started...");try{if (!cts.IsCancellationRequested){Console.WriteLine("Working...");await ProcessAsync(token);}}catch (OperationCanceledException e){Console.WriteLine(e.Message);Console.WriteLine("Service stopped");}}private async Task ProcessAsync(CancellationToken token){for (int i = 0; i < 100; i++){await semaphore.WaitAsync(token); // 等待信号量token.ThrowIfCancellationRequested();await Task.Delay(500, token);if (autoReleaseSemaphore){semaphore.Release(); // 只有当 autoReleaseSemaphore 为 true 时才 Release}else{continue;}Console.WriteLine($"Process.{i}");}}}
}
namespace taskTest
{internal class Program{static void Main(string[] args){MyService service = new();service.Start();// 等待一段时间,确保 ProcessAsync 有机会执行Console.ReadLine();//Thread.Sleep(1500);// 暂停服务service.Pause();Console.WriteLine("暂停了");Console.WriteLine("按下回车启动Resume");Console.ReadLine();Console.WriteLine("ReadLine执行完");service.Resume();Console.ReadLine();service.Stop();Console.ReadLine();}}
}

结果:

在这里插入图片描述

在PLC中的应用:

using S7.Net;
using System.Reflection;namespace taskTest
{public class S7ConnServiceImpl : IS7ConnService{public S7ConnServiceImpl(Db95DeviceHis db95DeviceHis){this.db95DeviceHis = db95DeviceHis;}private static readonly object lockObj = new object(); // 创建一个对象作为锁private Db95DeviceHis db95DeviceHis;private bool myIsConnected = false;private int errorTimes = 0;private CancellationTokenSource cts = new();private readonly SemaphoreSlim semaphore = new SemaphoreSlim(0, 1); // 初始为 0,Start() 启动时手动放行private volatile bool autoReleaseSemaphore = true; // 控制 ProcessAsync 是否自动 Releasepublic bool MyIsConnected{get => myIsConnected;set => myIsConnected = value;}private Plc? s7Plc = null;public Plc? S7Plc => s7Plc;public void ConnPlc(string myIp, int dbNum, int startByte){return;}public void ConnPlc(string myIp){autoReleaseSemaphore = true;semaphore.Release(); // 初始启动一次try{Task.Factory.StartNew(async () =>{while (!cts.IsCancellationRequested){if (s7Plc == null || !MyIsConnected){try{s7Plc = new Plc(CpuType.S71500, myIp, 0, 1);s7Plc.Open();s7Plc.ReadTimeout = 620;s7Plc.WriteTimeout = 620;//ctsRead1 = new();//ctsRead2 = new();MyIsConnected = s7Plc.IsConnected;if (MyIsConnected){Console.WriteLine("PlcSucessConn!");}}catch (PlcException ex){errorTimes++;s7Plc.Close();s7Plc = null;MyIsConnected = false;Console.WriteLine(ex.Message);Console.WriteLine("连接发生错误");Console.WriteLine(ex.GetType().Name);Console.WriteLine("ErrorsTime:" + errorTimes);await Task.Delay(2000);}}else if (MyIsConnected){try{MyIsConnected = s7Plc.IsConnected;await semaphore.WaitAsync(cts.Token); // 等待信号量cts.Token.ThrowIfCancellationRequested();await Task.Delay(200);errorTimes = 0;if (autoReleaseSemaphore){semaphore.Release(); // 只有当 autoReleaseSemaphore 为 true 时才 Release}else{continue;}var tempDb95DeviceHis =await S7Plc.ReadClassAsync<Db95DeviceHis>(95, 0);lock (lockObj){if (tempDb95DeviceHis != null){CopyProperties(tempDb95DeviceHis, db95DeviceHis);}Console.WriteLine(db95DeviceHis.Kr500Trigger);Console.WriteLine(db95DeviceHis.Kr16Time);}}catch (IOException ex){errorTimes++;await Task.Delay(2000);Console.WriteLine("读取发生错误");Console.WriteLine(ex.GetType().Name);Console.WriteLine($"读取时发生错误:{ex.Message}");Console.WriteLine($"读取时发生错误次数:{errorTimes}");s7Plc.Close();MyIsConnected = false;s7Plc = null;}}}},cts.Token,TaskCreationOptions.LongRunning,TaskScheduler.Default);}catch (OperationCanceledException e){Console.WriteLine(e.Message);Console.WriteLine("Service stopped");}}public void Pause(){Console.WriteLine("Pausing service...");autoReleaseSemaphore = false; // 禁止 ProcessAsync 自动 Release}public void Resume(){Console.WriteLine("Resuming service...");autoReleaseSemaphore = true; // 允许 ProcessAsync 自动 Releasesemaphore.Release(); // 手动触发一次 Release,唤醒阻塞的 WaitAsync}public void Stop(){Console.WriteLine("Stopping service...");cts.Cancel();}/// <summary>/// 反射复制属性值/// </summary>/// <param name="source"></param>/// <param name="destination"></param>/// <exception cref="ArgumentNullException"></exception>public void CopyProperties(object source, object destination){if (source == null || destination == null){throw new ArgumentNullException("Either source or destination is null.");}Type sourceType = source.GetType();Type targetType = destination.GetType();foreach (PropertyInfo sourceProperty in sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance)){PropertyInfo targetProperty = targetType.GetProperty(sourceProperty.Name);if (targetProperty != null&& targetProperty.CanWrite&& sourceProperty.PropertyType == targetProperty.PropertyType){targetProperty.SetValue(destination, sourceProperty.GetValue(source));}}}}
}
    public class Db95DeviceHis : INotifyPropertyChanged{public int Ret { get; set; }public float Kr16Time { get; set; }public float Kr500Time { get; set; }public float Dizuo1Time { get; set; }public float Dizuo2Time { get; set; }public float Dizuo3Time { get; set; }public float Kj1Time { get; set; }public float Kj2Time { get; set; }public float Kj3Time { get; set; }public float ZhouTime { get; set; }public float DamoTime { get; set; }public bool Kr16Trigger{get => kr16Trigger;set{if (kr16Trigger != value && value == true){NotifyPropertyChanged();}kr16Trigger = value;}}public bool Kr500Trigger{get => kr500Trigger;set{if (kr500Trigger != value && value == true){NotifyPropertyChanged();}kr500Trigger = value;}}private bool kr16Trigger;private bool kr500Trigger;public virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = ""){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}public event PropertyChangedEventHandler? PropertyChanged;}
    public interface IS7ConnService{void ConnPlc(string myIp, int dbNum, int startByte);void ConnPlc(string myIp);bool MyIsConnected{get;}Plc? S7Plc { get; }}

program主程序

        static void Main(string[] args){S7ConnServiceImpl serviceImpl = new(new Db95DeviceHis());serviceImpl.ConnPlc("192.168.2.10");Console.ReadLine();serviceImpl.Pause();Console.ReadLine();serviceImpl.Resume();Console.ReadLine();serviceImpl.Pause();Console.ReadLine();serviceImpl.Resume();Console.ReadLine();serviceImpl.Stop();Console.ReadLine();//MyService service = new();//service.Start(); 等待一段时间,确保 ProcessAsync 有机会执行//Console.ReadLine();Thread.Sleep(1500); 暂停服务//service.Pause();//Console.WriteLine("暂停了");//Console.WriteLine("按下回车启动Resume");//Console.ReadLine();//Console.WriteLine("ReadLine执行完");//service.Resume();//Console.ReadLine();//service.Stop();//Console.ReadLine();}

结果:
在这里插入图片描述

相关文章:

C# 的异步任务中, 如何暂停, 继续,停止任务

namespace taskTest {using System;using System.Threading;using System.Threading.Tasks;public class MyService{private Task? workTask;private readonly SemaphoreSlim semaphore new SemaphoreSlim(0, 1); // 初始为 0&#xff0c;Start() 启动时手动放行private read…...

langchain4j中使用milvus向量数据库做RAG增加索引

安装milvus向量数据库 官方网址 https://milvus.io/zh 使用docker安装milvus mkdir -p /data/docker/milvus cd /data/docker/milvus wget https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh#在docker中启动milvus sh standalone_emb…...

MySQL SQL Mode及其说明

以下是MySQL中所有支持的SQL Mode及其说明&#xff0c;综合了多个来源的信息并进行了分类整理&#xff1a; 一、严格模式相关 STRICT_TRANS_TABLES 对事务型存储引擎&#xff08;如InnoDB&#xff09;启用严格数据校验。若插入非法值&#xff08;如类型不符、超出范围等&#…...

Web前端最新导航

前言 本文列出了很多与前端有关的常见网站、博客、工具等&#xff0c;整体来看比较权威。有些东西已经过时了&#xff0c;我就不列出来了。学是一方面&#xff0c;也是最主要的方面&#xff1b;但还有一个作用&#xff0c;比如&#xff0c;“这个前端框架你都不知道啊”、“这个…...

2025年AI工程师认证深度解析:AAIA认证体系全景指南与实战策略

一、IAAAI认证体系演进与价值定位 1.1 国际人工智能认证发展现状 全球人工智能认证市场呈现显著分化态势。据Gartner 2025Q1报告显示&#xff0c;北美市场以IEEE/ACM双认证体系为主导&#xff08;市占率38%&#xff09;&#xff0c;欧盟区推行AI Act合规认证&#xff08;强制…...

CentOS 和 RHEL

CentOS 和 RHEL&#xff08;Red Hat Enterprise Linux&#xff09;关系非常紧密&#xff0c;简而言之&#xff1a; CentOS 最初是 RHEL 的免费、开源克隆版&#xff0c;几乎与 RHEL 二进制兼容。 CentOS 原是 RHEL 的“免费双胞胎”&#xff0c;但已被放弃&#xff0c;现在推荐…...

flask开启https服务支持

目录 一、背景 二、开启https支持 三、自签名 1、安装openssl 2、验证安装 3、自签名 四、编写代码 五、访问https接口 一、背景 最近在做自动化业务&#xff0c;需要兼容现在主流的框架开发的前端页面&#xff0c;于是到github找到了几个项目&#xff0c;clone下来项目并…...

统计服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息

文章目录 一、背景二、说明三、页面四、代码 前端 MonitorServiceProcessPage.vueMonitorServiceProcessTable.vueMonitorServiceProcessTableButton.vueaddMonitorTask.vueproductOperation.vueshowMonitorTask.vueMonitorSystemLog.vueMonitorTask.vueMonitorTaskLog.vueReal…...

【SGL】Scatter-Gather List内存传输技术

文章目录 1. What is SGL&#xff1f;2. sgl内存传输的原理2.1 核心思想2.2 sgl数据结构2.3 摘链和挂链 3. 零拷贝技术3.1 问题背景3.2 零拷贝的核心思想及实现方式 4. sgl在存储行业的应用 1. What is SGL&#xff1f; sgl&#xff08;Scatter-Gather List&#xff09;内存传…...

-MAC桢-

MAC桢和IP的关系&#xff1a; 主机A想跨网络和B通信需要IP地址进行路由选择&#xff0c;但一个局域网&#xff0c;比如路由器进行路由选择之前&#xff0c;首先要将数据包发送给路由器B&#xff0c;也就是局域网通信也就是同一个网段的主机进行通信&#xff0c;所以必须通过mac…...

安装:Kali2025+Docker

安装:Kali2025Docker Kali2025安装 直接官网下载WMware版本 https://www.kali.org/get-kali/#kali-virtual-machines 直接打开运行 初始用户密码 kali/kali sudo -i 命令切换到root 更换镜像 切换到其他可用的 Kali Linux 镜像源可能会解决问题,可以使用国内的镜像源&…...

Linux云计算训练营笔记day04[Rocky Linux中的命令:mv、cp、grep(^$)、tar、重定向>和>>]

mv 移动(剪切) 源数据会消失 格式: mv 源文件 目标路径 touch /opt/a.txt 创建文件 mv /opt/a.txt /root 移动文件&#xff0c;没有改名 mkdir gongli 创建目录 mv gongli /opt/ 移动目录&#xff0c;没有改名 mv /opt/gongli tedu 移动目录&#xff0c;改名了 …...

AbMole Olaparib:打破常规,用PARP抑制重塑肿瘤研究

在当今的生物医学研究领域&#xff0c;Olaparib&#xff08;AZD2281&#xff0c;AbMole&#xff0c;M1664&#xff09;作为一种重要的PARP&#xff08;聚腺苷二磷酸核糖聚合酶&#xff09;抑制剂&#xff0c;受到了广泛关注。Olaparib可干扰 DNA 单链断裂的修复&#xff0c;从而…...

RPC、gRPC和HTTP的区别

RPC 只是一种屏蔽远程过程调用的设计&#xff0c;它与HTTP不是对立的&#xff0c;两者不是一个层面的概念。 RPC底层通信可以使用TCP实现&#xff08;如Thrift&#xff09;&#xff0c;也可以使用HTTP实现&#xff08;如gRPC&#xff09;&#xff0c;其本身并无限制。 1. 概念…...

Windows重置网络,刷新缓存

同时按键盘上的【Windows】键和【S】键&#xff0c;弹出搜索框&#xff0c;输入 命令提示符 在“最佳匹配”下的【命令提示符】上右键&#xff0c;点击【以管理员身份运行】 1弹出一个窗口&#xff0c;在光标闪烁的位置&#xff0c;直接输入【netsh winsock reset】&#xff0…...

Ref是什么

在 React 中&#xff0c;ref 是一种用于访问 DOM 元素或组件实例的机制。它允许你在组件中直接操作 DOM 元素&#xff0c;或者访问子组件的实例。ref 的使用场景非常广泛&#xff0c;包括表单操作、焦点控制、动画等。以下是关于 ref 的详细讲解以及在项目中的常见使用场景。 …...

OpenHarmony平台驱动开发(十),MMC

OpenHarmony平台驱动开发&#xff08;十&#xff09; MMC 概述 功能简介 MMC&#xff08;MultiMedia Card&#xff09;即多媒体卡&#xff0c;是一种用于固态非易失性存储的小体积大容量的快闪存储卡。 MMC后续泛指一个接口协定&#xff08;一种卡式&#xff09;&#xff0…...

解决IDEA无法运行git的问题

之前git一直没有问题&#xff0c;今天打开就提示我安装git&#xff0c;自然用git去提交新项目也会遇到问题。 我出现问题的原因是&#xff1a;git路径缺失 文件->设置->git 发现git的路径为空&#xff0c;按照实际位置填写即可...

HTTP 响应状态码总结

一、引言 HTTP 响应状态码是超文本传输协议&#xff08;HTTP&#xff09;中服务器对客户端&#xff08;通常是 Web 浏览器&#xff09;请求的响应指示。这些状态码是三位数字代码&#xff0c;用于告知客户端请求的结果&#xff0c;包括请求是否成功。响应被分为五个类别&#…...

Java求职面试:Spring Boot与微服务的幽默探讨

Java求职者面试&#xff1a;技术与幽默的碰撞 场景概述 在某互联网大厂的面试现场&#xff0c;面试官严肃认真&#xff0c;程序员则是一个搞笑的水货角色。面试者名叫张伟&#xff0c;年龄28岁&#xff0c;硕士学历&#xff0c;拥有5年的Java开发经验。以下是面试的详细过程。…...

lua脚本+Redission实现分布式锁

实现分布式锁最简单的一种方式&#xff1a;基于Redis 不论是本地锁还是分布式锁&#xff0c;核心都在于“互斥”。 在 Redis 中&#xff0c; SETNX 命令是可以帮助我们实现互斥。SETNX 即 set if not exists (对应 Java 中的 setIfAbsent 方法)&#xff0c;如果 key 不存在的…...

JVM之jcmd命令详解

jcmd 是 Oracle JDK&#xff08;Java Development Kit&#xff09;自 JDK 7 起引入的一个强大的诊断工具&#xff0c;用于与正在运行的 JVM&#xff08;Java Virtual Machine&#xff09;实例进行交互。它允许用户执行各种诊断命令&#xff0c;比如线程堆栈分析、堆转储、GC 信…...

Go语言:json 作用和语法

在 Go 语言中&#xff0c;JSON 字段&#xff08;也称为 JSON Tag&#xff09;是附加在结构体字段上的元数据&#xff0c;用于控制该字段在 JSON 编码&#xff08;序列化&#xff09;和解码&#xff08;反序列化&#xff09; 时的行为。它的语法是&#xff1a; type StructName…...

Hive HA配置高可用

Hive的高可用性(HA)通过消除关键组件的单点故障来实现,确保系统在部分故障时仍能正常运行。其基本原理涉及以下核心组件和策略: ‌1. Hive Metastore 的高可用‌ ‌ 多实例部署‌:部署多个Metastore服务实例,每个实例连接到共享的后端数据库(如MySQL、PostgreSQ…...

Ubuntu 第11章 网络管理_常用的网络配置命令

为了管理网络&#xff0c;Linux提供了许多非常有用的网络管理命令。利用这些命令&#xff0c;一方面可以有效地管理网络&#xff0c;另一方面出现网络故障时&#xff0c;可以快速进行诊断。本节将对Ubuntu提供的网络管理命令进行介绍。 11.2.1 ifconfig命令 关于ifconfig命令&…...

【Qt】Qt 构建系统详解:qmake 入门到项目实战

Qt 构建系统详解&#xff1a;qmake 入门到项目实战 本文将系统介绍 Qt 构建工具 qmake 的用法&#xff0c;并通过一个完整的项目结构示例&#xff0c;帮助你掌握 .pro 文件编写、子项目管理、模块依赖等核心技能。 &#x1f9ed; 一、什么是 qmake&#xff1f; qmake 是 Qt 提…...

Python实例题:pygame开发打飞机游戏

目录 Python实例题 题目 pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本 代码解释 初始化部分&#xff1a; 游戏主循环&#xff1a; 退出部分&#xff1a; 运行思路 注意事项 Python实例题 题目 pygame开发打飞机游戏 pygame-aircraft-game使用 Pygame 开发…...

《Zabbix Proxy分布式监控实战:从安装到配置全解析》

注意&#xff1a;实验所需的zabbix服务器的搭建可参考博客 zabbix 的docker安装_docker安装zabbix-CSDN博客 1.1 实验介绍 1.1.1 实验目的 本实验旨在搭建一个基于Zabbix的监控系统&#xff0c;通过安装和配置Zabbix Proxy、MySQL数据库以及Zabbix Agent&#xff0c;实现分…...

华为配置篇-RSTP/MSTP实验

MSTP 一、简介二、常用命令总结三、实验 一、简介 RSTP&#xff08;快速生成树协议&#xff09;​ RSTP&#xff08;Rapid Spanning Tree Protocol&#xff09;是 STP 的改进版本&#xff0c;基于 ​​IEEE 802.1w 标准​​&#xff0c;核心目标是解决传统 STP 收敛速度慢的问…...

git如何将本地 dev 分支与远程 dev 分支同步

要让本地 dev 分支与远程 dev 分支完全同步&#xff08;丢弃本地多余的提交记录&#xff09;&#xff0c;可以按照以下步骤操作&#xff1a; 1. ​​获取远程最新状态​ git fetch origin dev # 拉取远程 dev 分支的最新提交&#xff0c;但不会修改本地代码 IDEA中点击fetc…...