感谢您的持续关注!以下是继续补充的 .NET Core(现为 .NET,如 .NET 5/6/7/8)在上位机开发中常用的方法和编程方式,延续之前的详细说明,重点针对大数据量、硬件交互和高实时性需求场景。本部分将增加更多方法,涵盖网络通信、数据库操作、日志记录、配置文件管理以及其他现代化特性,确保内容全面且实用。每种方法都会提供详细说明、示例代码、上位机适用场景、注意事项,并与 .NET Framework 对比。
十、现代化开发与架构(续)
-
Configuration Management (Microsoft.Extensions.Configuration)
-
功能:提供灵活的配置管理,支持 JSON、XML、环境变量等多种配置源,适合动态加载上位机参数。
-
上位机场景:加载硬件配置(如串口参数、PLC 地址)或系统设置(如采集频率)。
-
示例:从 JSON 文件加载串口配置:
csharp
using Microsoft.Extensions.Configuration; public class HardwareConfig { public string PortName { get; init; } public int BaudRate { get; init; } } public class HardwareManager { private readonly HardwareConfig _config; public HardwareManager(IConfiguration configuration) { _config = configuration.GetSection("Hardware").Get<HardwareConfig>(); } public void Start() { using var serialPort = new SerialPort(_config.PortName, _config.BaudRate); serialPort.Open(); Console.WriteLine($"Connected to {_config.PortName} at {_config.BaudRate}"); } } // appsettings.json { "Hardware": { "PortName": "COM1", "BaudRate": 9600 } } public static IConfiguration BuildConfiguration() { return new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .Build(); }
-
注意事项:
-
使用 reloadOnChange: true 支持运行时配置更新。
-
确保配置文件的访问权限,特别是在嵌入式设备上。
-
-
优势:集中管理配置,支持动态更新,适合工业环境的多设备配置。
-
对比 .NET Framework:Framework 依赖 System.Configuration,功能较简单,缺乏 JSON 支持和动态加载。
-
-
Logging (Microsoft.Extensions.Logging)
-
功能:提供结构化日志框架,支持多目标输出(如控制台、文件、远程服务)。
-
上位机场景:记录硬件通信、数据处理错误或性能指标。
-
示例:记录传感器数据处理日志:
csharp
using Microsoft.Extensions.Logging; public class DataProcessor { private readonly ILogger<DataProcessor> _logger; public DataProcessor(ILogger<DataProcessor> logger) { _logger = logger; } public async Task ProcessDataAsync(byte[] data) { _logger.LogInformation("Processing data of length {Length}", data.Length); try { await Task.Delay(10); // 模拟处理 } catch (Exception ex) { _logger.LogError(ex, "Failed to process data"); } } } public static ILoggerFactory BuildLoggerFactory() { return LoggerFactory.Create(builder => { builder.AddConsole(); builder.AddFile("logs/app.log"); }); }
-
注意事项:
-
使用 ILoggerFactory 配置日志目标(如 Serilog 集成更强大的功能)。
-
控制日志级别(Information、Error),避免过多日志影响性能。
-
-
优势:结构化日志易于分析,适合工业环境中的调试和监控。
-
对比 .NET Framework:Framework 依赖 Trace 或第三方库(如 log4net),配置复杂且性能稍逊。
-
十一、数据库与数据存储
-
Entity Framework Core (EF Core)
-
功能:轻量级 ORM,支持异步查询和批量操作,优化数据库交互。
-
上位机场景:存储传感器数据到数据库(如 SQLite、SQL Server)。
-
示例:异步保存传感器数据:
csharp
using Microsoft.EntityFrameworkCore; public class SensorData { public int Id { get; set; } public double Value { get; set; } public DateTime Timestamp { get; set; } } public class AppDbContext : DbContext { public DbSet<SensorData> SensorData { get; set; } public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } } public async Task SaveSensorDataAsync(SensorData data) { using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetService<AppDbContext>(); dbContext.SensorData.Add(data); await dbContext.SaveChangesAsync(); } // 配置 SQLite 数据库 public static IServiceProvider BuildServiceProvider() { var services = new ServiceCollection(); services.AddDbContext<AppDbContext>(options => options.UseSqlite("Data Source=sensors.db")); return services.BuildServiceProvider(); }
-
注意事项:
-
使用异步方法(如 SaveChangesAsync)避免阻塞。
-
批量插入优化性能(如 AddRangeAsync)。
-
-
优势:异步查询和轻量级设计,适合高吞吐量数据存储(每秒 1000 条+)。
-
对比 .NET Framework:EF Core 比 EF 6 更轻量,性能更高,支持跨平台。
-
-
SqlBulkCopy (System.Data.SqlClient)
-
功能:高效批量插入数据到 SQL Server,适合大数据量。
-
上位机场景:存储大量传感器数据(如每秒 10 万条)。
-
示例:
csharp
using System.Data.SqlClient; public async Task BulkInsertDataAsync(List<SensorData> dataList) { using var connection = new SqlConnection("Server=localhost;Database=Sensors;Trusted_Connection=True;"); await connection.OpenAsync(); using var bulkCopy = new SqlBulkCopy(connection); bulkCopy.DestinationTableName = "SensorData"; var dataTable = new DataTable(); dataTable.Columns.Add("Id", typeof(int)); dataTable.Columns.Add("Value", typeof(double)); dataTable.Columns.Add("Timestamp", typeof(DateTime)); foreach (var data in dataList) { dataTable.Rows.Add(data.Id, data.Value, data.Timestamp); } await bulkCopy.WriteToServerAsync(dataTable); }
-
注意事项:
-
确保表结构匹配 DataTable。
-
使用事务提高一致性。
-
-
优势:批量插入性能极高,适合大数据量场景。
-
对比 .NET Framework:功能类似,但 .NET Core 的异步支持更强。
-
十二、网络通信
-
HttpClient with HttpClientFactory
-
功能:优化 HTTP 请求管理,支持连接池和异步操作。
-
上位机场景:与云端或远程服务器通信(如上传传感器数据到 Azure IoT Hub)。
-
示例:
csharp
using System.Net.Http; using Microsoft.Extensions.DependencyInjection; public class CloudService { private readonly IHttpClientFactory _clientFactory; public CloudService(IHttpClientFactory clientFactory) { _clientFactory = clientFactory; } public async Task SendDataAsync(SensorData data) { var client = _clientFactory.CreateClient(); var content = JsonContent.Create(data); var response = await client.PostAsync("https://api.example.com/data", content); response.EnsureSuccessStatusCode(); } } public static IServiceProvider BuildServiceProvider() { var services = new ServiceCollection(); services.AddHttpClient(); return services.BuildServiceProvider(); }
-
注意事项:
-
使用 IHttpClientFactory 管理 HttpClient 生命周期,避免端口耗尽。
-
配置超时和重试策略(结合 Polly)。
-
-
优势:高效、可靠的 HTTP 通信,适合云集成。
-
对比 .NET Framework:Framework 的 HttpClient 易导致资源泄漏,需手动管理。
-
-
gRPC
-
功能:高性能 RPC 框架,适合低延迟、高吞吐量通信。
-
上位机场景:与远程工业设备或服务器通信(如实时控制指令)。
-
示例:
csharp
// proto 文件 service DataService { rpc SendSensorData (SensorDataRequest) returns (SensorDataResponse); } // C# 客户端 using Grpc.Net.Client; public class GrpcClient { private readonly DataService.DataServiceClient _client; public GrpcClient() { var channel = GrpcChannel.ForAddress("https://localhost:5001"); _client = new DataService.DataServiceClient(channel); } public async Task SendDataAsync(SensorData data) { var request = new SensorDataRequest { Id = data.Id, Value = data.Value }; var response = await _client.SendSensorDataAsync(request); Console.WriteLine($"Response: {response.Status}"); } }
-
注意事项:
-
配置 gRPC 通道(HTTP/2)以优化性能。
-
确保服务器支持 gRPC。
-
-
优势:低延迟(<10ms),高吞吐量,适合实时通信。
-
对比 .NET Framework:Framework 无内置 gRPC 支持,需使用第三方库。
-
十三、其他实用方法
-
System.Text.Json
-
功能:高性能 JSON 序列化/反序列化,替代 Newtonsoft.Json。
-
上位机场景:序列化传感器数据以发送到云端或存储。
-
示例:
csharp
using System.Text.Json; public async Task SerializeDataAsync(SensorData data) { using var stream = new MemoryStream(); await JsonSerializer.SerializeAsync(stream, data, new JsonSerializerOptions { WriteIndented = true }); Console.WriteLine($"Serialized: {Encoding.UTF8.GetString(stream.ToArray())}"); }
-
注意事项:
-
使用 JsonSerializerOptions 配置序列化行为(如忽略 null 值)。
-
对于复杂对象,可能需自定义转换器。
-
-
优势:性能高于 Newtonsoft.Json,内存占用低。
-
对比 .NET Framework:Framework 依赖 Newtonsoft.Json,性能稍逊。
-
-
PeriodicTimer
-
功能:提供高精度定时器,支持异步定时任务。
-
上位机场景:周期性采集硬件数据(如每 50ms 读取一次)。
-
示例:
csharp
public async Task RunPeriodicAcquisitionAsync(CancellationToken ct) { using var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(50)); while (await timer.WaitForNextTickAsync(ct)) { byte[] data = await ReadFromHardwareAsync(); Console.WriteLine($"Data collected: {data.Length} bytes"); } }
-
注意事项:
-
确保任务执行时间短于定时间隔,防止任务堆积。
-
使用 CancellationToken 控制停止。
-
-
优势:异步友好,高精度,适合实时性要求。
-
对比 .NET Framework:Framework 依赖 System.Timers.Timer,异步支持较弱。
-
-
ValueTuple
-
功能:轻量级元组类型,支持多值返回,性能优于匿名类型。
-
上位机场景:从硬件读取多种数据(如 ID 和值)。
-
示例:
csharp
public async ValueTask<(int Id, double Value)> ReadSensorAsync() { byte[] buffer = new byte[12]; int bytesRead = await _serialPort.BaseStream.ReadAsync(buffer); return (buffer[0], BitConverter.ToDouble(buffer, 4)); }
-
注意事项:
-
使用命名元组提高可读性:
csharp
return (Id: buffer[0], Value: BitConverter.ToDouble(buffer, 4));
-
-
优势:减少对象分配,适合高频调用。
-
对比 .NET Framework:Framework 支持 Tuple,但性能较低。
-
十四、综合示例:完整上位机应用
以下是一个综合示例,整合多种方法,展示实时采集、处理、存储和显示的完整上位机流程:
csharp
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.IO.Ports;
using System.Text.Json;
using System.Threading.Channels;
using System.Threading.Tasks.Dataflow;
public record SensorData(int Id, double Value, DateTime Timestamp);
public class HardwareManager
{
private readonly SerialPort _serialPort;
private readonly ILogger<HardwareManager> _logger;
public HardwareManager(IConfiguration config, ILogger<HardwareManager> logger)
{
var portName = config["Hardware:PortName"];
var baudRate = int.Parse(config["Hardware:BaudRate"]);
_serialPort = new SerialPort(portName, baudRate);
_serialPort.Open();
_logger = logger;
}
public async ValueTask<byte[]> ReadAsync(CancellationToken ct)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
int bytesRead = await _serialPort.BaseStream.ReadAsync(buffer, ct);
_logger.LogInformation("Read {Bytes} bytes from hardware", bytesRead);
return buffer.AsSpan(0, bytesRead).ToArray();
}
catch (Exception ex)
{
_logger.LogError(ex, "Hardware read failed");
throw;
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
}
public class DataProcessor
{
private readonly Channel<SensorData> _dataChannel = Channel.CreateBounded<SensorData>(10000);
private readonly HardwareManager _hardware;
private readonly ILogger<DataProcessor> _logger;
private readonly TransformBlock<byte[], SensorData> _parseBlock;
private readonly ActionBlock<SensorData> _storeBlock;
public DataProcessor(HardwareManager hardware, ILogger<DataProcessor> logger)
{
_hardware = hardware;
_logger = logger;
_parseBlock = new TransformBlock<byte[], SensorData>(
data => new SensorData(data[0], BitConverter.ToDouble(data, 1), DateTime.Now),
new ExecutioncouponDataflowBlockOptions { MaxDegreeOfParallelism = 2 });
_storeBlock = new ActionBlock<SensorData>(
async data => await StoreAsync(data),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1 });
_parseBlock.LinkTo(_storeBlock, new DataflowLinkOptions { PropagateCompletion = true });
}
public async Task StartAcquisitionAsync(CancellationToken ct)
{
using var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(50));
while (await timer.WaitForNextTickAsync(ct))
{
byte[] rawData = await _hardware.ReadAsync(ct);
await _parseBlock.SendAsync(rawData, ct);
}
}
public async Task ProcessDataAsync(CancellationToken ct)
{
await _storeBlock.Completion;
}
private async Task StoreAsync(SensorData data)
{
// 模拟存储到数据库或云端
await Task.Delay(10);
_logger.LogInformation("Stored: {Data}", JsonSerializer.Serialize(data));
}
}
public class Program
{
public static async Task Main()
{
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole());
services.AddSingleton<IConfiguration>(BuildConfiguration());
services.AddSingleton<HardwareManager>();
services.AddSingleton<DataProcessor>();
var provider = services.BuildServiceProvider();
var processor = provider.GetService<DataProcessor>();
using var cts = new CancellationTokenSource();
var acquisitionTask = processor.StartAcquisitionAsync(cts.Token);
var processingTask = processor.ProcessDataAsync(cts.Token);
Console.ReadLine();
cts.Cancel();
await Task.WhenAll(acquisitionTask, processingTask);
}
private static IConfiguration BuildConfiguration()
{
return new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
}
}
// appsettings.json
{
"Hardware": {
"PortName": "COM1",
"BaudRate": 9600
}
}
示例说明:
-
硬件交互:HardwareManager 使用 SerialPort 和 ValueTask 异步读取数据,结合 ArrayPool 优化内存。
-
数据处理:DataProcessor 使用 Channel 和 Dataflow 构建采集-解析-存储管道,支持高并发。
-
配置管理:通过 IConfiguration 加载 JSON 配置。
-
日志记录:使用 ILogger 记录操作和错误。
-
定时采集:PeriodicTimer 每 50ms 采集一次数据,满足高实时性。
-
现代化特性:record 定义数据模型,DI 管理服务。
十五、总结
常用方法汇总(补充后):
-
异步与并发:Task.Run, Task.WhenAll, Parallel.ForEachAsync, Channels, ValueTask, Dataflow, IAsyncEnumerable, PeriodicTimer.
-
内存优化:Span<T>, Memory<T>, ArrayPool<T>, RecyclableMemoryStream, Pipelines.
-
硬件交互:System.IO.Ports(异步增强)、OPC UA Client, Modbus.Net.
-
数据库:EF Core, SqlBulkCopy.
-
网络通信:HttpClientFactory, gRPC.
-
UI 管理:.NET MAUI, Dispatcher.
-
并发安全:Concurrent Collections, Interlocked, ReaderWriterLockSlim.
-
容错:Polly, CancellationToken.
-
诊断:System.Diagnostics.Metrics, EventSource.
-
现代化开发:Records, Init-only Properties, Pattern Matching, Dependency Injection, Configuration, Logging, System.Text.Json, ValueTuple.
上位机优势:
-
大数据量:Span<T>, Pipelines, IAsyncEnumerable, SqlBulkCopy 处理每秒 100MB+ 数据,内存效率高。
-
硬件交互:异步 API(ReadAsync, OPC UA, Modbus)降低延迟(<50ms),支持现代协议。
-
高实时性:ValueTask, PeriodicTimer, Parallel.ForEachAsync 满足 <10ms 延迟需求。
-
现代化开发:MAUI, DI, Configuration, Logging 提高可维护性和跨平台能力。
对比 .NET Framework:
-
.NET Core 提供更高性能(延迟低 20%-50%)、跨平台支持、现代化特性。
-
Framework 缺乏 Span<T>, IAsyncEnumerable, Pipelines, gRPC 等,异步和内存优化较弱。
若需更具体的实现(如特定硬件协议、数据库类型、UI 框架)或性能优化建议,请提供更多细节,我可进一步定制代码!