手撸WPF工业级MES系统实战
这系统不仅要扛住产线实时数据轰炸,还得玩转AGV调度、库位管理这些骚操作,代码里全是实战干货。现在系统稳如老狗,管你几百台设备同时发数据,数据库连接数稳稳的。这里用了生产者-消费者模式,采集线程疯狂灌数据,UI线程定时取最新值。是自己封装的,必须读满指定字节数,否则在网卡的时候容易出幺蛾子。处理完的命令直接扔进队列,由专门的调度线程处理,避免阻塞网络IO。这种数据驱动的方式比直接操作UI控件优雅多
工业 MES 系统源代码 Wpf C# WPF开发。 WPF MES 上位机产线执行系统。 1, 完整纯源代码; 2, AGV自动调度; 3, SQLSERVER数据库。 带附加文件。 4, WPF各种技术应用。 5, 数据库技术应用。 6, DTU数据传输。 7, TCP IP SOCKET技术应用。 8, EXCEL数据查询与导出。 9, 各种库位的管理。 10,重要是多线程技术应用。
最近在车间蹲了三个月搞出来的WPF版MES系统,今天挑几个硬核技术点跟大伙唠唠。这系统不仅要扛住产线实时数据轰炸,还得玩转AGV调度、库位管理这些骚操作,代码里全是实战干货。
UI与业务解耦玩到飞起

WPF的数据绑定和MVVM模式必须得整明白了。看这段库存看板的XAML:
<ItemsControl ItemsSource="{Binding Bins}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Status,Converter={StaticResource StatusToBrush}}">
<StackPanel>
<TextBlock Text="{Binding Code}" FontWeight="Bold"/>
<TextBlock Text="{Binding MaterialName}"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
对应的ViewModel直接上ObservableCollection动态刷新:
public class WarehouseVM : INotifyPropertyChanged
{
private ObservableCollection<Bin> _bins = new();
public ObservableCollection<Bin> Bins
{
get => _bins;
set => SetField(ref _bins, value);
}
// 库位状态变化时触发界面更新
private void OnAGVMoved(AGVMessage msg)
{
var targetBin = Bins.FirstOrDefault(b => b.Code == msg.TargetBin);
targetBin.Status = BinStatus.Occupied;
}
}
这种数据驱动的方式比直接操作UI控件优雅多了,特别是当AGV调度触发库位状态变化时,界面自动跟着跑,真香!
多线程生存指南
产线数据采集每秒上百条记录,不上多线程分分钟卡成狗。看这个数据采集器的双缓冲队列:
private ConcurrentQueue<DeviceData> _dataBuffer = new();
private readonly object _syncLock = new();
// 采集线程
void CollectData()
{
while (!_cancellationToken.IsCancellationRequested)
{
var rawData = _plc.Read(); // 耗时IO操作
_dataBuffer.Enqueue(ParseData(rawData));
if (_dataBuffer.Count >= 100)
{
lock (_syncLock)
{
// 批量插入数据库
var temp = _dataBuffer.ToArray();
_db.BulkInsert(temp);
_dataBuffer.Clear();
}
}
}
}
// UI定时器显示最新数据
void RefreshTimer_Tick(object sender, EventArgs e)
{
lock (_syncLock)
{
var latest = _dataBuffer.LastOrDefault();
CurrentSpeed = latest?.Speed ?? 0;
}
}
这里用了生产者-消费者模式,采集线程疯狂灌数据,UI线程定时取最新值。注意那个双重锁——既要保证批量插入的原子性,又要避免UI卡顿。

工业 MES 系统源代码 Wpf C# WPF开发。 WPF MES 上位机产线执行系统。 1, 完整纯源代码; 2, AGV自动调度; 3, SQLSERVER数据库。 带附加文件。 4, WPF各种技术应用。 5, 数据库技术应用。 6, DTU数据传输。 7, TCP IP SOCKET技术应用。 8, EXCEL数据查询与导出。 9, 各种库位的管理。 10,重要是多线程技术应用。
TCP/IP通讯的坑
跟AGV小车通讯用Socket,最头疼的就是粘包问题。咱们自定义了个简单协议:
// 协议格式:4字节长度头 + JSON内容
async Task HandleClient(TcpClient client)
{
var stream = client.GetStream();
var headerBuffer = new byte[4];
while (true)
{
// 读包头
await stream.ReadExactlyAsync(headerBuffer, 0, 4);
int bodyLength = BitConverter.ToInt32(headerBuffer, 0);
// 读包体
var bodyBuffer = new byte[bodyLength];
await stream.ReadExactlyAsync(bodyBuffer, 0, bodyLength);
var json = Encoding.UTF8.GetString(bodyBuffer);
var cmd = JsonConvert.DeserializeObject<AGVCommand>(json);
// 扔到任务队列处理
_commandQueue.Add(cmd);
}
}
ReadExactlyAsync是自己封装的,必须读满指定字节数,否则在网卡的时候容易出幺蛾子。处理完的命令直接扔进队列,由专门的调度线程处理,避免阻塞网络IO。

Excel导出神操作
车间主任最爱要Excel报表,用EPPlus库比Interop强十条街:
public void ExportToExcel(IEnumerable<ProductionRecord> records)
{
using var package = new ExcelPackage();
var sheet = package.Workbook.Worksheets.Add("生产报表");
// 设置标题样式
sheet.Cells[1,1].Value = "日期";
sheet.Cells[1,2].Value = "良品率";
using(var range = sheet.Cells[1,1,1,2])
{
range.Style.Font.Bold = true;
range.Style.Fill.PatternType = ExcelFillStyle.Solid;
range.Style.Fill.BackgroundColor.SetColor(Color.LightBlue);
}
// 填充数据
int row = 2;
foreach (var r in records)
{
sheet.Cells[row, 1].Value = r.Date.ToString("yyyy-MM-dd");
sheet.Cells[row, 2].Value = r.YieldRate;
row++;
}
// 自适应列宽
sheet.Cells[sheet.Dimension.Address].AutoFitColumns();
File.WriteAllBytes("Report.xlsx", package.GetAsByteArray());
}
这比用COM组件快得多,而且不怕进程残留。注意样式设置要放在循环外面,否则生成大文件时内存会爆炸。
搞工业软件最刺激的就是各种突发状况——上周五AGV小车突然集体抽风,后来发现是线程池被数据库查询堵死了。赶紧上了SemaphoreSlim做限流:
private SemaphoreSlim _dbThrottler = new(10, 10); // 最大10并发
async Task QueryYieldRate()
{
await _dbThrottler.WaitAsync();
try
{
using var conn = new SqlConnection(_connStr);
await conn.QueryAsync<YieldData>("SELECT...");
}
finally
{
_dbThrottler.Release();
}
}
现在系统稳如老狗,管你几百台设备同时发数据,数据库连接数稳稳的。下次有机会再聊聊怎么用Redis做实时看板的二级缓存,那又是另一个血泪故事了。

更多推荐
所有评论(0)