.NET Core 中上位机开发常用的方法和编程方式的详细说明之四
对比 .NET Framework:Framework 提供同步方法(如 File.WriteAllText),异步支持需手动实现,性能较低。对比 .NET Framework:Framework 的 Stream 支持异步,但 .NET Core 性能更高,API 更现代化。对比 .NET Framework:Framework 支持 Rx.NET,但 .NET Core 集成更紧密,性能更高。
本文将继续补充 .NET Core(现为 .NET,如 .NET 5/6/7/8)在上位机开发中常用的方法和编程方式,延续之前的详细说明,重点针对大数据量、硬件交互和高实时性需求场景。以下内容将进一步扩展,增加更多实用方法,涵盖文件操作、序列化、事件驱动、跨平台支持、测试与调试等,确保覆盖上位机开发的广泛需求。每种方法提供详细说明、示例代码、上位机适用场景、注意事项,并与 .NET Framework 对比。
十六、文件操作与存储
-
System.IO Asynchronous File Operations
-
功能:提供异步文件读写方法(如 File.ReadAllBytesAsync, File.WriteAllTextAsync),优化 I/O 性能。
-
上位机场景:存储传感器数据到文件(如日志或历史数据),适合高吞吐量场景。
-
示例:异步写入传感器数据到 CSV 文件:
csharp
public async Task SaveDataToFileAsync(SensorData data, string filePath) { string csvLine = $"{data.Id},{data.Value},{data.Timestamp:O}"; await File.AppendAllTextAsync(filePath, csvLine + Environment.NewLine); } public async Task ReadDataFromFileAsync(string filePath) { string content = await File.ReadAllTextAsync(filePath); // 解析 CSV foreach (var line in content.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries)) { var parts = line.Split(','); var data = new SensorData(int.Parse(parts[0]), double.Parse(parts[1]), DateTime.Parse(parts[2])); Console.WriteLine($"Read: {data}"); } }
-
注意事项:
-
使用异步方法避免阻塞,特别是在 UI 线程。
-
确保文件路径权限,特别是在嵌入式设备上。
-
对于大数据量,考虑分块写入:
csharp
using var stream = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read, bufferSize: 4096, useAsync: true); await stream.WriteAsync(dataBuffer);
-
-
优势:异步 I/O 减少阻塞,适合高实时性场景(<50ms 延迟)。
-
对比 .NET Framework:Framework 提供同步方法(如 File.WriteAllText),异步支持需手动实现,性能较低。
-
-
System.IO.Stream with Asynchronous Buffering
-
功能:结合 Stream 的异步方法(如 ReadAsync, WriteAsync)和缓冲区管理,优化文件或网络流处理。
-
上位机场景:处理大文件(如 GB 级数据备份)或实时流(如硬件数据流)。
-
示例:异步写入大数据到文件:
csharp
public async Task WriteLargeDataAsync(byte[] data, string filePath) { using var stream = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: 8192, useAsync: true); await stream.WriteAsync(data.AsMemory()); }
-
注意事项:
-
配置合适的缓冲区大小(bufferSize),通常为 4KB 或 8KB。
-
使用 ArrayPool 管理缓冲区,减少内存分配:
csharp
byte[] buffer = ArrayPool<byte>.Shared.Rent(8192); try { int bytesRead = await sourceStream.ReadAsync(buffer); await targetStream.WriteAsync(buffer.AsMemory(0, bytesRead)); } finally { ArrayPool<byte>.Shared.Return(buffer); }
-
-
优势:高效处理大文件或流,适合 GB 级数据存储。
-
对比 .NET Framework:Framework 的 Stream 支持异步,但 .NET Core 性能更高,API 更现代化。
-
十七、事件驱动与消息处理
-
System.Reactive (Rx.NET)
-
功能:提供反应式编程模型,处理异步事件流,支持复杂事件处理(如过滤、聚合)。
-
上位机场景:实时监控传感器数据,触发事件(如阈值报警)。
-
示例:监控传感器数据并触发报警:
csharp
using System.Reactive.Linq; public IObservable<SensorData> ObserveSensorDataAsync() { return Observable.Create<SensorData>(async observer => { using var cts = new CancellationTokenSource(); while (!cts.Token.IsCancellationRequested) { byte[] rawData = await ReadFromHardwareAsync(); var data = new SensorData(rawData[0], BitConverter.ToDouble(rawData, 1), DateTime.Now); observer.OnNext(data); await Task.Delay(50, cts.Token); } }); } public void MonitorData() { ObserveSensorDataAsync() .Where(data => data.Value > 100.0) // 过滤高值 .Subscribe(data => Console.WriteLine($"Alarm: High value {data.Value} at {data.Timestamp}")); }
-
注意事项:
-
使用 SubscribeOn 和 ObserveOn 控制线程:
csharp
.SubscribeOn(TaskPoolScheduler.Default) .ObserveOn(DispatcherScheduler.Current)
-
管理订阅生命周期,调用 Dispose 避免泄漏。
-
-
优势:声明式事件处理,适合实时监控和复杂逻辑。
-
对比 .NET Framework:Framework 支持 Rx.NET,但 .NET Core 集成更紧密,性能更高。
-
-
EventHandler with Async Support
-
功能:支持异步事件处理,结合 async/await 实现非阻塞事件响应。
-
上位机场景:处理硬件数据到达事件(如串口数据接收)。
-
示例:
csharp
public class HardwareManager { public event Func<SensorData, Task> DataReceived; public async Task StartAsync(CancellationToken ct) { while (!ct.IsCancellationRequested) { byte[] rawData = await ReadFromHardwareAsync(); var data = new SensorData(rawData[0], BitConverter.ToDouble(rawData, 1), DateTime.Now); if (DataReceived != null) { await DataReceived.Invoke(data); } } } } public class DataProcessor { public DataProcessor(HardwareManager manager) { manager.DataReceived += async (data) => { await ProcessDataAsync(data); }; } private async Task ProcessDataAsync(SensorData data) { await Task.Delay(10); // 模拟处理 Console.WriteLine($"Processed: {data}"); } }
-
注意事项:
-
使用 async void 仅限于事件处理程序。
-
确保事件处理程序异常不会中断主流程:
csharp
try { await DataReceived.Invoke(data); } catch { /* 记录错误 */ }
-
-
优势:异步事件处理,适合高实时性场景。
-
对比 .NET Framework:Framework 的事件处理通常同步,异步支持需手动实现。
-
十八、跨平台与嵌入式支持
-
System.Device.Gpio
-
功能:提供 GPIO 操作,适用于嵌入式设备(如 Raspberry Pi)。
-
上位机场景:控制工业设备 GPIO 引脚(如开关继电器)。
-
示例:
csharp
using System.Device.Gpio; public class GpioControllerService { private readonly GpioController _controller; public GpioControllerService() { _controller = new GpioController(); } public void TogglePin(int pinNumber, bool state) { _controller.OpenPin(pinNumber, PinMode.Output); _controller.Write(pinNumber, state ? PinValue.High : PinValue.Low); } }
-
注意事项:
-
确保设备支持 GPIO(如 Raspberry Pi)。
-
检查权限,特别是在 Linux 系统上。
-
-
优势:跨平台支持,适合嵌入式上位机。
-
对比 .NET Framework:Framework 无内置 GPIO 支持,需第三方库。
-
-
System.Runtime.InteropServices for Cross-Platform P/Invoke
-
功能:优化 P/Invoke 调用,支持跨平台调用本地库(如 Linux 的 libserialport)。
-
上位机场景:访问低级硬件接口(如自定义串口驱动)。
-
示例:
csharp
using System.Runtime.InteropServices; public class NativeSerialPort { [DllImport("libserialport.so", EntryPoint = "sp_get_port_by_name")] private static extern IntPtr GetPortByName(string portName); public void OpenPort(string portName) { IntPtr port = GetPortByName(portName); // 继续本地调用 Console.WriteLine($"Opened port: {portName}"); } }
-
注意事项:
-
使用 [DllImport] 指定平台特定的库名称。
-
提供 Windows 和 Linux 的实现路径:
csharp
private const string LibName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "kernel32.dll" : "libserialport.so";
-
-
优势:支持跨平台硬件交互,适合 Linux 工控机。
-
对比 .NET Framework:Framework 的 P/Invoke 仅限 Windows,跨平台支持差。
-
十九、测试与调试
-
xUnit with Async Testing
-
功能:支持异步单元测试,验证上位机逻辑。
-
上位机场景:测试数据处理或硬件交互逻辑。
-
示例:
csharp
using Xunit; public class DataProcessorTests { [Fact] public async Task ProcessDataAsync_ValidData_Succeeds() { var processor = new DataProcessor(); var data = new SensorData(1, 100.0, DateTime.Now); await processor.ProcessDataAsync(data); Assert.True(true); // 验证逻辑 } }
-
注意事项:
-
使用 async Task 而非 async void。
-
模拟硬件交互以避免测试依赖:
csharp
public class MockHardwareManager : IHardwareManager { public async ValueTask<byte[]> ReadAsync(CancellationToken ct) { return new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 }; // 模拟数据 } }
-
-
优势:异步测试支持,适合验证高并发逻辑。
-
对比 .NET Framework:Framework 的测试框架(如 MSTest)异步支持较弱。
-
-
BenchmarkDotNet
-
功能:高性能基准测试工具,分析方法性能。
-
上位机场景:优化数据解析或硬件交互性能。
-
示例:
csharp
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; [MemoryDiagnoser] public class DataParserBenchmarks { private readonly byte[] _data = new byte[1024]; [Benchmark] public int ParseWithSpan() { return BitConverter.ToInt32(_data.AsSpan()); } [Benchmark] public int ParseWithArray() { return BitConverter.ToInt32(_data); } } public static void Main() { BenchmarkRunner.Run<DataParserBenchmarks>(); }
-
注意事项:
-
运行在 Release 模式,确保准确结果。
-
分析内存分配和执行时间,优化关键路径。
-
-
优势:精确测量性能,适合优化实时性(如 <10ms 延迟)。
-
对比 .NET Framework:Framework 支持 BenchmarkDotNet,但 .NET Core 性能分析更精准。
-
二十、综合示例:增强版上位机应用
以下是一个更复杂的综合示例,整合更多方法,展示实时采集、处理、存储、通信和监控:
csharp
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Device.Gpio;
using System.IO.Pipelines;
using System.Reactive.Linq;
using System.Text.Json;
using System.Threading.Channels;
public record SensorData(int Id, double Value, DateTime Timestamp);
public interface IHardwareManager
{
ValueTask<byte[]> ReadAsync(CancellationToken ct);
void TogglePin(int pinNumber, bool state);
}
public class HardwareManager : IHardwareManager
{
private readonly GpioController _gpio;
private readonly ILogger<HardwareManager> _logger;
private readonly PipeReader _pipeReader;
public HardwareManager(IConfiguration config, ILogger<HardwareManager> logger)
{
_gpio = new GpioController();
_logger = logger;
_pipeReader = CreatePipeReader(); // 模拟硬件数据流
}
public async ValueTask<byte[]> ReadAsync(CancellationToken ct)
{
var result = await _pipeReader.ReadAsync(ct);
var buffer = result.Buffer;
try
{
if (buffer.Length >= 8)
{
var slice = buffer.Slice(0, 8);
_logger.LogInformation("Read {Length} bytes", slice.Length);
return slice.ToArray();
}
return Array.Empty<byte>();
}
finally
{
_pipeReader.AdvanceTo(buffer.Start, buffer.End);
}
}
public void TogglePin(int pinNumber, bool state)
{
_gpio.OpenPin(pinNumber, PinMode.Output);
_gpio.Write(pinNumber, state ? PinValue.High : PinValue.Low);
}
private PipeReader CreatePipeReader()
{
var pipe = new Pipe();
Task.Run(async () =>
{
while (true)
{
await pipe.Writer.WriteAsync(new byte[] { 1, 0, 0, 0, 0, 0, 0, 0 });
await Task.Delay(50);
}
});
return pipe.Reader;
}
}
public class DataProcessor
{
private readonly Channel<SensorData> _dataChannel = Channel.CreateBounded<SensorData>(10000);
private readonly IHardwareManager _hardware;
private readonly ILogger<DataProcessor> _logger;
private readonly IObservable<SensorData> _dataObservable;
public DataProcessor(IHardwareManager hardware, ILogger<DataProcessor> logger)
{
_hardware = hardware;
_logger = logger;
_dataObservable = Observable.Create<SensorData>(async observer =>
{
while (true)
{
byte[] rawData = await _hardware.ReadAsync(CancellationToken.None);
var data = new SensorData(rawData[0], BitConverter.ToDouble(rawData, 1), DateTime.Now);
observer.OnNext(data);
}
});
}
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);
var data = new SensorData(rawData[0], BitConverter.ToDouble(rawData, 1), DateTime.Now);
await _dataChannel.Writer.WriteAsync(data, ct);
_hardware.TogglePin(18, data.Value > 100); // 控制 GPIO
}
}
public void MonitorHighValues()
{
_dataObservable
.Where(data => data.Value > 100)
.Subscribe(data => _logger.LogWarning("High value detected: {Value}", data.Value));
}
public async Task SaveToFileAsync(CancellationToken ct)
{
await foreach (var data in _dataChannel.Reader.ReadAllAsync(ct))
{
string json = JsonSerializer.Serialize(data);
await File.AppendAllTextAsync("data.json", json + Environment.NewLine, ct);
}
}
}
public class Program
{
public static async Task Main()
{
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole());
services.AddSingleton<IConfiguration>(new ConfigurationBuilder().AddJsonFile("appsettings.json").Build());
services.AddSingleton<IHardwareManager, HardwareManager>();
services.AddSingleton<DataProcessor>();
var provider = services.BuildServiceProvider();
var processor = provider.GetService<DataProcessor>();
using var cts = new CancellationTokenSource();
processor.MonitorHighValues();
var acquisitionTask = processor.StartAcquisitionAsync(cts.Token);
var saveTask = processor.SaveToFileAsync(cts.Token);
Console.ReadLine();
cts.Cancel();
await Task.WhenAll(acquisitionTask, saveTask);
}
}
示例说明:
-
硬件交互:HardwareManager 使用 System.IO.Pipelines 和 System.Device.Gpio 模拟硬件数据流和 GPIO 控制。
-
数据处理:DataProcessor 使用 Channel, PeriodicTimer, System.Reactive 实现实时采集和监控。
-
存储:异步写入 JSON 文件(System.Text.Json 和 File.AppendAllTextAsync)。
-
现代化特性:DI, Logging, record, 提高代码可维护性。
二十一、总结
新增方法汇总:
-
文件操作:File.ReadAllBytesAsync, File.WriteAllTextAsync, Stream 异步方法。
-
事件驱动:System.Reactive, Async EventHandler.
-
跨平台:System.Device.Gpio, System.Runtime.InteropServices.
-
测试与调试:xUnit 异步测试, BenchmarkDotNet.
-
综合:整合 Configuration, Logging, DI, Pipelines, Reactive 等。
上位机优势:
-
大数据量:Pipelines, File 异步方法处理 GB 级数据流,内存效率高。
-
硬件交互:GPIO, P/Invoke 支持嵌入式设备,异步方法降低延迟。
-
高实时性:PeriodicTimer, Reactive 实现 <50ms 实时监控。
-
跨平台:支持 Linux 工控机,适合混合部署。
-
调试与维护:xUnit, BenchmarkDotNet 优化性能和可靠性。
对比 .NET Framework:
-
.NET Core 提供更高性能(延迟低 20%-50%)、跨平台支持、现代化 API。
-
Framework 缺乏 Pipelines, GPIO, System.Text.Json, 异步文件操作等,开发效率和性能较差。
若需针对特定场景(如特定硬件协议、数据量、实时性要求)提供更详细代码或优化,请提供更多细节!

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)