广州网站建设的价格,库尔勒西部建设网站,做花馍网站,建设网站需要做的工作内容MES开发中, 客户往往会要求 工单开始时记录工艺数据, 工单结束时将这些工艺数据回传到更上一级的WES系统中. 因为MES系统和PLC 是多线程读取, 所以加锁, 事件触发是常用手段.
using MyWebApiTest.PLC;
using MyWebApiTest.Service;
using MyWebApiTest.Service.Entry;
using M…MES开发中, 客户往往会要求 工单开始时记录工艺数据, 工单结束时将这些工艺数据回传到更上一级的WES系统中. 因为MES系统和PLC 是多线程读取, 所以加锁, 事件触发是常用手段.
using MyWebApiTest.PLC;
using MyWebApiTest.Service;
using MyWebApiTest.Service.Entry;
using MyWebApiTest.Service.Entry.Imp;
using MyWebApiTest.Service.Factory;
using MyWebApiTest.Service.Factory.Impl;
using MyWebApiTest.Utils;
using Serilog;var builder WebApplication.CreateBuilder(args);// Add services to the container.//日志
builder.Host.UseSerilog((context, logger)
{logger.ReadFrom.Configuration(context.Configuration);logger.Enrich.FromLogContext();
});// Add services to the container.
builder.Configuration.AddJsonFile(appsettings.json, false, true);
var cfg builder.Configuration;
builder.Services.AddSingletonIConfiguration(cfg);//ORM
builder.Services.AddSingletonISqlSugarService ,SqlSugarServiceImpl();
builder.Services.AddSingletonSqlSugarHelper();builder.Services.AddSingletonIAbsFactoryService, AbsFactoryServiceImpl();builder.Services.AddSingletonIConnFactoryService, ConnFactoryServiceImpl2();
builder.Services.AddSingletonIConnFactoryService, ConnFactoryServiceImpl1();//PLC数据
builder.Services.AddSingletonMyS7Entry();
builder.Services.AddSingletonIS7ConnService, S7ConnServiceImpl();//运行初始化任务 测试client
//builder.Services.AddSingletonIHostedService, StartupInitializationService();//client
builder.Services.AddHttpClient();//AutoMapper
builder.Services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());builder.Services.AddControllers();
builder.Services.AddCors(c c.AddPolicy(any, p p.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()));
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();//日志
builder.Host.UseSerilog((context, logger)
{logger.ReadFrom.Configuration(context.Configuration);logger.Enrich.FromLogContext();
});var app builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}
app.UseCors(any);app.UseAuthorization();app.MapControllers();app.Run();
using S7.Net;namespace MyWebApiTest.Service.Entry
{public interface IS7ConnService{void ConnPlc();bool MyIsConnected{get;}Plc MyS7Master { get; }}
}
using MyWebApiTest.PLC;
using MyWebApiTest.Service.Entry;
using S7.Net;namespace MyWebApiTest.Service.Entry.Imp
{public class S7ConnServiceImpl : IS7ConnService{public S7ConnServiceImpl(IConfiguration configuration,HttpClient httpClient,ILoggerS7ConnServiceImpl logger,MyS7Entry myS7Entry){this.configuration configuration;this.httpClient httpClient;this.logger logger;this.myS7Entry myS7Entry;myIp configuration.GetSection(PlcIp).Value;}private readonly IConfiguration configuration;private readonly HttpClient httpClient;private readonly ILoggerS7ConnServiceImpl logger;private MyS7Entry myS7Entry;private string myIp;private Plc myS7Master null;private MyS7EntityRecive? myS7test new MyS7EntityRecive();private MyS7Entry myS7Data new MyS7Entry();private bool myIsConnected false;private CancellationTokenSource cts new();private int errorTimes 0;private static readonly object lockObj new object(); // 创建一个对象作为锁public Plc MyS7Master{get myS7Master;}public MyS7Entry MyS7Data{get myS7Data;set myS7Data value;}public bool MyIsConnected{get myIsConnected;set{if (myIsConnected false value true){logger.LogInformation(PLC连接成功!);}myIsConnected value;}}public void ConnPlc(){Task.Run(async () {while (!cts.IsCancellationRequested){if (myS7Master null || !MyIsConnected){try{myS7Master new Plc(CpuType.S71500, myIp, 0, 0);myS7Master.Open();MyIsConnected myS7Master.IsConnected;}catch (Exception ex){myS7Master?.Close();myS7Master null;MyIsConnected false;logger.LogError(ex.Message);await Task.Delay(2000);}}else if (MyIsConnected){//注入Client//var url http://localhost:5190/api/private/v1/My/MyGet; // 目标 Web API 的地址//var response await httpClient.GetAsync(url);//if (response.IsSuccessStatusCode)//{// var content await response.Content.ReadAsStringAsync();// logger.LogError(content);//}try{MyIsConnected myS7Master.IsConnected;await Task.Delay(1000);myS7test await myS7Master.ReadClassAsyncMyS7EntityRecive(31, 416);lock (lockObj){myS7Entry.MyShort1 myS7test.MyShort1;myS7Entry.MyShort2 myS7test.MyShort2;}logger.LogInformation(myS7Entry.MyShort1.ToString() );}catch (Exception ex){errorTimes;await Task.Delay(1000);logger.LogError($读取时发生错误:{ex.Message});logger.LogError($读取时发生错误次数:{errorTimes});myS7Master.Close();MyIsConnected false;myS7Master null;}}}}, cts.Token);}}
}/*使用了 lock 来保护 myS7Entry.MyShort1 和 myS7Entry.MyShort2 的同时修改
以确保在同一时间只有一个线程可以修改这两个属性。这是一种常见的使用锁的方式
目的是避免竞态条件和数据不一致性。死锁通常发生在两个或多个线程之间存在循环依赖锁的情况下
导致它们互相等待对方释放锁。在你的代码中只有一个 lock并且在修改属性时使用
不会导致循环依赖锁因此不会发生死锁。但要注意死锁可能在其他情况下发生比如在涉及多个锁的复杂情况下
或者在锁嵌套的情况下。确保你的代码中不会出现多个锁之间的循环依赖
以及在锁内部避免阻塞线程以保证代码的正常执行。*/using System.ComponentModel;namespace MyWebApiTest.PLC
{public class MyS7Entry : INotifyPropertyChanged{public event PropertyChangedEventHandler? PropertyChanged;private short myShort1;public short MyShort1{get myShort1;set{if (myShort1 ! value){if (myShort1 1 value 0){OnPropertyChanged(nameof(MyShort1));}myShort1 value;}}}private short myShort2;public short MyShort2{get myShort2;set{if (myShort2 ! value){if (myShort2 1 value 0){OnPropertyChanged(nameof(MyShort2));}myShort2 value;}}}private void OnPropertyChanged(string propertyName){PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));}}
}
namespace MyWebApiTest.PLC
{public class MyS7EntityRecive{public short MyShort1 { get; set; }public short MyShort2 { get; set; }}
}
using MyWebApiTest.entities;
using MyWebApiTest.PLC;
using MyWebApiTest.Service.Entry;
using System.Text.Json;namespace MyWebApiTest.Utils
{public class StartupInitializationService : IHostedService{private readonly MyS7Entry myS7Entry;private readonly IS7ConnService s7ConnService;private readonly ILoggerStartupInitializationService logger;private readonly HttpClient httpClient;public StartupInitializationService(MyS7Entry myS7Entry, IS7ConnService s7ConnService, ILoggerStartupInitializationService logger, HttpClient httpClient){this.myS7Entry myS7Entry;this.s7ConnService s7ConnService;this.logger logger;this.httpClient httpClient;}public Task StartAsync(CancellationToken cancellationToken){try{s7ConnService.ConnPlc();}catch (Exception ex){logger.LogError($网络错误:{ex.Message});return Task.CompletedTask;}logger.LogWarning(初始化函数成功);myS7Entry.PropertyChanged async (s, e) {if (e.PropertyName MyShort1){string? url http://127.0.0.1:8081/endpoint/mes/kx/reportA;Student stu new(){Id 1,Name MyBool1,Age 999};var json JsonSerializer.Serialize(stu);var content new StringContent(json, System.Text.Encoding.UTF8, application/json);var response await httpClient.PostAsync(url, content);if (response.IsSuccessStatusCode){logger.LogInformation(Data sent successfullyS1.);}else{logger.LogInformation(Failed to send dataS1.);}}else if (e.PropertyName MyShort2){string? url http://127.0.0.1:8081/endpoint/mes/kx/reportB;Student stu new(){Id 2,Name MyBool2,Age 888};var json JsonSerializer.Serialize(stu);var content new StringContent(json, System.Text.Encoding.UTF8, application/json);var response await httpClient.PostAsync(url, content);if (response.IsSuccessStatusCode){logger.LogInformation(Data sent successfullyS1.);}else{logger.LogInformation(Failed to send dataS1.);}}};return Task.CompletedTask;}public Task StopAsync(CancellationToken cancellationToken){// 在应用程序停止时执行清理逻辑如果有必要return Task.CompletedTask;}}
}