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();}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/80901.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于nextjs中next-sitemap插件生成文件样式丢失问题及自定义样式处理

现象没有默认样式 修改后 代码配置如下 next-sitemap.config.js如下 // const { routing } require(./src/i18n/routing) ;const { flatten } require(lodash) const fs require(fs); const path require(path);// 改为硬编码locales值&#xff0c;与routing.ts保持一…

图片的require问题

问题 <template><!--第一种方式--><img :src"require(/assets/${imageName})" style"width:100px;" /><!--第二种方式--><img :src"require(imageUrl)" style"width:100px;" /> </template><…

【官方题解】StarryCoding 入门教育赛 2 | acm | 蓝桥杯 | 新手入门

比赛传送门&#xff1a; 本场比赛开始时题面存在一些问题&#xff0c;私密马赛&#xff01; A.池化【入门教育赛】 根据题目所给公式计算即可。 #include "bits/stdc.h"signed main() {int t; std::cin >> t;while (t --) {int l, k, s, p; std::cin >&…

课题推荐——低成本地磁导航入门,附公式推导和MATLAB例程运行演示

地磁导航利用地球磁场的自然特性&#xff0c;通过感知磁场变化&#xff0c;帮助机器人或无人设备实现定位和导航。相比于 GPS、激光雷达等导航方法&#xff0c;地磁导航具有以下优势&#xff1a; 低成本&#xff1a;使用地磁传感器&#xff08;如电子罗盘&#xff09;&#xff…

【人工智能】自然语言编程革命:腾讯云CodeBuddy实战5步搭建客户管理系统,效率飙升90%

CodeBuddy 导读一、产品介绍1.1 **什么是腾讯云代码助手&#xff1f;**1.2 插件安装1.2.1 IDE版本要求1.2.2 注意事项1.2.4 插件安装1.2.4.1 环境安装1.2.4.2 安装腾讯云AI代码助手** 1.2.5 功能介绍1.2.5.1 Craft&#xff08;智能代码生成&#xff09;1.2.5.2 Chat&#xff08…

游戏引擎学习第270天:生成可行走的点

回顾并为今天的内容定下基调 今天的计划虽然还不完全确定&#xff0c;可能会做一些内存分析&#xff0c;也有可能暂时不做&#xff0c;因为目前并没有特别迫切的需求。最终我们会根据当下的状态随性决定&#xff0c;重点是持续推动项目的进展&#xff0c;无论是 memory 方面还…

Java反射详细介绍

的反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时动态获取类的信息、操作类的成员&#xff08;属性、方法、构造器&#xff09;&#xff0c;甚至修改类的行为。它是框架开发&#xff08;如 Spring、MyBatis&#xff09;、单元测试工具&a…

c语言第一个小游戏:贪吃蛇小游戏05

贪吃蛇脱缰自动向右走&#xff1a;脱缰的野蛇 #include <curses.h> #include <stdlib.h> struct snake{ int hang; int lie; struct snake *next; }; struct snake *head; struct snake *tail; void initNcurse() { initscr(); keypad(stdscr,1); } int …

react-diff-viewer 如何实现语法高亮

前言 react-diff-viewer 是一个很好的 diff 展示库&#xff0c;但是也有一些坑点和不完善的地方&#xff0c;本文旨在描述如何在这个库中实现自定义语法高亮。 Syntax highlighting is a bit tricky when combined with diff. Here, React Diff Viewer provides a simple rend…

coco数据集mAP评估

0 coco数据集划分说明 1 用yolo自带的评估 from ultralytics import YOLOmodel YOLO("../spatial-perception/checkpoints/yolo11n.pt")metrics model.val(data"./coco.yaml", save_jsonTrue) ## save_json为True,可以把预测结果存成json文件&#xff…

sensitive-word-admin v2.0.0 全新 ui 版本发布!vue+前后端分离

前言 sensitive-word-admin 最初的定位是让大家知道如何使用 sensitive-word&#xff0c;所以开始想做个简单的例子。 不过秉持着把一个工具做好的原则&#xff0c;也收到很多小伙伴的建议。 v2.0.0 在 ruoyi-vue&#xff08;也非常感谢若依作者多年来的无私奉献&#xff09…

好消息!PyCharm 社区版现已支持直接选择 WSL 终端为默认终端

在过去&#xff0c;PyCharm 社区版虽然提供了链接 Windows 子系统 Linux&#xff08;WSL&#xff09;终端的能力&#xff0c;但用户无法在设置中直接指定 WSL 为默认终端&#xff0c;这一功能仅限于专业版使用者。 而现在&#xff0c;在 PyCharm 2025.1.1 版本中&#xff0c;Je…

【Redis】string 字符串

文章目录 string 字符串常用命令设置和获取setgetmget & mset 计数操作incr & incrbydecr & decrbyincrbyfloat 字符串操作appendstrlengetrangesetrange 应用场景 string 字符串 关于 Redis 的字符串&#xff0c;有几点需要注意 Redis 所有的 key 的类型都是字符…

本地部署firecrawl的两种方式,自托管和源码部署

网上资料很多 AI爬虫黑科技 firecrawl本地部署-CSDN博客 源码部署 前提条件本地安装py&#xff0c;node.js环境,嫌弃麻烦直接使用第二种 使用git或下载压缩包 git clone https://github.com/mendableai/firecrawl.git 设置环境参数 cd /firecrawl/apps/api 复制环境参数 …

(三)毛子整洁架构(Infrastructure层/DapperHelper/乐观锁)

文章目录 项目地址一、Infrastructure Layer1.1 创建Application层需要的服务1. Clock服务2. Email 服务3. 注册服务 1.2 数据库服务1. 表配置Configurations2. Respository实现3. 数据库链接Factory实现4. Dapper的DataOnly服务实现5. 所有数据库服务注册 1.3 基于RowVersion的…

uni-app微信小程序登录流程详解

文章目录 uni-app微信小程序登录流程实战详解微信小程序登录流程概述1. 获取登录凭证&#xff08;code&#xff09;2. 发送登录请求3. 保存登录态4. 登录状态管理5. 应用登录状态请求拦截器中添加 token自动登录页面路由守卫 使用 Vuex 集中管理登录状态登录组件示例登录流程最…

GUC并发编程和SpringCloud,二者之间的关系

一.提问 我认为&#xff0c;Java开发中&#xff0c;如果项目的每一个小模块需要不同人员并行开发时&#xff0c;就需要使用SpringCloud&#xff1b;如果要解决系统用户激增&#xff0c;就是用GUC并发编程。 这个说法对么&#xff1f; 二.解答 你的理解部分正确&#xff0c;但不…

在 Vue 3 中使用 canvas-confetti 插件

&#x1f389; 在 Vue 3 中使用 canvas-confetti 插件 canvas-confetti 是一个轻量、无依赖的 JavaScript 动画库&#xff0c;用于在网页上展示彩带、庆祝动画。非常适合用于抽奖、支付成功、活动庆祝等场景。 本教程将指导你如何在 Vue 3 项目中集成并使用该插件。 &#x1…

深入解析Spring Boot项目目录结构:从新手到规范实践

一、标准项目结构全景图 典型的Spring Boot项目&#xff08;Maven构建&#xff09;目录结构如下&#xff1a; my-spring-project/ ├── src/ │ ├── main/ │ │ ├── java/ # 核心代码 │ │ │ └── com/ │ │ │ └── exa…

【C语言】宏经典练习题,交换奇偶位

交换奇偶位 写一个宏&#xff0c;可以将一个整数的二进制位的奇数位和偶数位交换。 #define Swap(x) x(((x&0x55555555)<<1)((x&0xaaaaaaaa)>>1)) int main() {int a 10;Swap(a);printf("%d\n", a);return 0; } 写宏的思路&#xff1a; 假设…