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

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 System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using S7.Net;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("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 (PlcException ex){errorTimes++;await Task.Delay(2000);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; }}

相关文章:

  • AKS 支持 Kata Container容器沙盒 -预览阶段
  • 什么是AI写作
  • [QMT量化交易小白入门]-五十一、用Backtrader搭建双均线策略回测平台,年化收益13%
  • Nginx静态资源增加权限验证
  • 计算机二级(C语言)已过
  • Rust 中的 `String`、`str` 和 `str`:深入解析与使用指南
  • Java设计模式之工厂方法模式:从入门到精通
  • 高效管理钉钉收款单数据集成到MySQL的技术方案
  • C——数组和函数实践:扫雷
  • Flutter 3.29.3 花屏问题记录
  • 机器学习第二讲:对比传统编程:解决复杂规则场景
  • CurrentHashMap的整体系统介绍及Java内存模型(JVM)介绍
  • AI Agent(7):Agent规划与决策能力
  • 等保系列(三):等保测评的那些事
  • 【Spring AI 实战】基于 Docker Model Runner 构建本地化 AI 聊天服务:从配置到函数调用全解析
  • 从 Git 到 GitHub - 使用 Git 进行版本控制 - Git 常用命令
  • AI云防护真的可以防攻击?你的服务器用群联AI云防护吗?
  • 基于OpenCV的人脸识别:EigenFaces算法
  • 【愚公系列】《Manus极简入门》028-创业规划顾问:“创业导航仪”
  • TB6600HG-富利威
  • 上海“电子支付费率成本为0”背后:金融服务不仅“快”和“省”,更有“稳”和“准”
  • 上汽享道出行完成13亿元C轮融资,已启动港股IPO计划
  • 人民财评:网售“婴儿高跟鞋”?不能让畸形审美侵蚀孩子身心
  • 阿森纳被打得毫无脾气,回天无力的阿尔特塔只剩嘴硬
  • 万里云端遇见上博--搭乘“上博号”主题飞机体验记
  • 自然资源部印发地理信息数据分类分级指南