编辑
2025-09-19
C#
00

目录

💡 为什么选择AOP方案?
🔍 传统方案的痛点
✨ AOP方案的优势
🛠️ 核心技术架构
性能监控特性定义+性能拦截器核心实现
🏭 实战案例:工业订单管理系统
🎯 业务场景
📦 业务服务实现
MainViewModel
🔧 依赖注入配置
🎯 关键:代理服务注册
MainWindow
UI
📊 性能数据收集器
🎯 智能数据管理
🎨 可视化监控界面
📈 实时图表展示
🎯 实战效果展示
📊 监控数据类型
🔍 性能分析能力
💡 核心优势总结
🎯 技术优势
🛠️ 实用技巧
🚀 扩展建议
📈 进阶功能
🎯 最佳实践

"你的C#应用慢得像老牛拉车?用户投诉系统卡顿?"

在工业管理系统中,性能问题往往是致命的。一个订单处理慢了几秒钟,可能就是几万块的损失。传统的性能监控方案要么侵入性太强,要么监控不够细致。

今天,我们用一个真实的工业订单管理系统来演示如何通过AOP(面向切面编程)+ Castle.DynamicProxy实现零侵入的性能监控,让你的系统性能一目了然!

💡 为什么选择AOP方案?

🔍 传统方案的痛点

C#
// 传统方式:代码侵入性强,维护困难 public async Task<bool> ProcessOrderAsync(Order order) { var stopwatch = Stopwatch.StartNew(); // 手动插入 try { // 业务逻辑 await DoBusinessLogic(order); return true; } finally { stopwatch.Stop(); LogPerformance(stopwatch.ElapsedMilliseconds); // 手动插入 } }

✨ AOP方案的优势

  • 零侵入:业务代码保持纯净
  • 统一管理:所有性能监控逻辑集中处理
  • 灵活配置:通过特性控制监控范围
  • 易维护:修改监控逻辑不影响业务代码

🛠️ 核心技术架构

性能监控特性定义+性能拦截器核心实现

C#
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using Castle.DynamicProxy; namespace AppIndustrialAop { // 性能监控属性定义 [AttributeUsage(AttributeTargets.Method)] public class PerformanceMonitorAttribute : Attribute { public string Description { get; set; } public PerformanceMonitorAttribute(string description = "") { Description = description; } } // 性能监控拦截器 public class PerformanceInterceptor : IInterceptor { private readonly IPerformanceLogger _logger; public PerformanceInterceptor(IPerformanceLogger logger) { _logger = logger; } public void Intercept(IInvocation invocation) { var stopwatch = Stopwatch.StartNew(); var methodName = $"{invocation.TargetType.Name}.{invocation.Method.Name}"; try { // 执行目标方法 invocation.Proceed(); } catch (Exception ex) { _logger.LogError(methodName, ex); throw; } finally { stopwatch.Stop(); var elapsedMs = stopwatch.ElapsedMilliseconds; // 记录性能数据 _logger.LogPerformance(methodName, elapsedMs); // 如果执行时间超过阈值,记录警告 if (elapsedMs > 500) { _logger.LogWarning(methodName, elapsedMs); } } } } }

🏭 实战案例:工业订单管理系统

🎯 业务场景

  • 订单处理:复杂的计算和数据库操作
  • 生产调度:设备分配和时间规划
  • 性能要求:响应时间必须在合理范围内

📦 业务服务实现

C#
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AppIndustrialAop { public interface IPerformanceLogger { void LogPerformance(string methodName, long elapsedMs); void LogWarning(string methodName, long elapsedMs); void LogError(string methodName, Exception ex); ObservableCollection<PerformanceRecord> GetPerformanceRecords(); List<PerformanceMetrics> GetPerformanceMetrics(); List<MethodPerformanceStats> GetMethodStats(); } }
C#
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; namespace AppIndustrialAop { public class PerformanceLogger : IPerformanceLogger, INotifyPropertyChanged { private readonly ObservableCollection<PerformanceRecord> _performanceRecords; private readonly Dictionary<string, List<long>> _methodPerformanceHistory; private readonly object _lock = new object(); public PerformanceLogger() { _performanceRecords = new ObservableCollection<PerformanceRecord>(); _methodPerformanceHistory = new Dictionary<string, List<long>>(); } public void LogPerformance(string methodName, long elapsedMs) { lock (_lock) { // 记录到历史数据 if (!_methodPerformanceHistory.ContainsKey(methodName)) { _methodPerformanceHistory[methodName] = new List<long>(); } _methodPerformanceHistory[methodName].Add(elapsedMs); // 保持最近500条记录 if (_methodPerformanceHistory[methodName].Count > 500) { _methodPerformanceHistory[methodName].RemoveAt(0); } } Application.Current.Dispatcher.Invoke(() => { _performanceRecords.Add(new PerformanceRecord { MethodName = methodName, ElapsedMilliseconds = elapsedMs, Timestamp = DateTime.Now, Status = elapsedMs > 500 ? "警告" : "正常" }); // 保持最近1000条记录 if (_performanceRecords.Count > 1000) { _performanceRecords.RemoveAt(0); } }); } public void LogWarning(string methodName, long elapsedMs) { Console.WriteLine($"⚠️ 性能警告: {methodName} 执行时间过长 ({elapsedMs}ms)"); } public void LogError(string methodName, Exception ex) { Console.WriteLine($"❌ 错误: {methodName} 执行异常 - {ex.Message}"); } public ObservableCollection<PerformanceRecord> GetPerformanceRecords() { return _performanceRecords; } public List<PerformanceMetrics> GetPerformanceMetrics() { lock (_lock) { var metrics = new List<PerformanceMetrics>(); var now = DateTime.Now; for (int i = 0; i < 60; i++) { var timePoint = now.AddSeconds(-i); var recordsAtTime = _performanceRecords .Where(r => r.Timestamp >= timePoint.AddSeconds(-1) && r.Timestamp < timePoint) .ToList(); metrics.Add(new PerformanceMetrics { Timestamp = timePoint, AverageResponseTime = recordsAtTime.Any() ? recordsAtTime.Average(r => r.ElapsedMilliseconds) : 0, RequestCount = recordsAtTime.Count, ErrorCount = recordsAtTime.Count(r => r.Status == "错误") }); } return metrics.OrderBy(m => m.Timestamp).ToList(); } } public List<MethodPerformanceStats> GetMethodStats() { lock (_lock) { var stats = new List<MethodPerformanceStats>(); foreach (var kvp in _methodPerformanceHistory) { var values = kvp.Value; if (values.Any()) { stats.Add(new MethodPerformanceStats { MethodName = kvp.Key, AverageTime = values.Average(), MinTime = values.Min(), MaxTime = values.Max(), CallCount = values.Count, P95Time = CalculatePercentile(values, 95), P99Time = CalculatePercentile(values, 99) }); } } return stats.OrderByDescending(s => s.AverageTime).ToList(); } } private double CalculatePercentile(List<long> values, int percentile) { var sorted = values.OrderBy(x => x).ToList(); int index = (int)Math.Ceiling(percentile / 100.0 * sorted.Count) - 1; return sorted[Math.Max(0, Math.Min(index, sorted.Count - 1))]; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } // 4. 数据模型定义 public class PerformanceRecord { public string MethodName { get; set; } public long ElapsedMilliseconds { get; set; } public DateTime Timestamp { get; set; } public string Status { get; set; } } public class PerformanceMetrics { public DateTime Timestamp { get; set; } public double AverageResponseTime { get; set; } public int RequestCount { get; set; } public int ErrorCount { get; set; } } public class MethodPerformanceStats { public string MethodName { get; set; } public double AverageTime { get; set; } public long MinTime { get; set; } public long MaxTime { get; set; } public int CallCount { get; set; } public double P95Time { get; set; } public double P99Time { get; set; } } public class Order : INotifyPropertyChanged { private string _orderId; private string _customerName; private int _quantity; private string _product; private DateTime _orderTime; private string _status; public string OrderId { get => _orderId; set { _orderId = value; OnPropertyChanged(); } } public string CustomerName { get => _customerName; set { _customerName = value; OnPropertyChanged(); } } public int Quantity { get => _quantity; set { _quantity = value; OnPropertyChanged(); } } public string Product { get => _product; set { _product = value; OnPropertyChanged(); } } public DateTime OrderTime { get => _orderTime; set { _orderTime = value; OnPropertyChanged(); } } public string Status { get => _status; set { _status = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class ProductionSchedule { public string ScheduleId { get; set; } public string OrderId { get; set; } public string Equipment { get; set; } public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } public int EstimatedDuration { get; set; } } // 5. 业务服务接口和实现 public interface IOrderService { Task<bool> ProcessOrderAsync(Order order); Task<List<Order>> GetOrdersAsync(); Task<bool> UpdateOrderStatusAsync(string orderId, string status); } public class OrderService : IOrderService { private readonly List<Order> _orders; private readonly IProductionScheduleService _scheduleService; private readonly Random _random; public OrderService(IProductionScheduleService scheduleService) { _orders = new List<Order>(); _scheduleService = scheduleService; _random = new Random(); } [PerformanceMonitor("订单处理")] public virtual async Task<bool> ProcessOrderAsync(Order order) { // 模拟复杂的订单处理逻辑 await Task.Delay(_random.Next(100, 800)); // 模拟网络延迟和数据库操作 // 计算生产时间 var productionTime = await CalculateProductionTimeAsync(order); // 创建生产调度 var schedule = new ProductionSchedule { ScheduleId = Guid.NewGuid().ToString(), OrderId = order.OrderId, Equipment = GetAvailableEquipment(order.Product), StartTime = DateTime.Now.AddHours(1), EndTime = DateTime.Now.AddHours(1 + productionTime), EstimatedDuration = productionTime }; // 保存到生产调度 await _scheduleService.CreateScheduleAsync(schedule); // 保存订单到数据库 await SaveOrderToDatabaseAsync(order); order.Status = "已调度"; return true; } [PerformanceMonitor("生产时间计算")] private async Task<int> CalculateProductionTimeAsync(Order order) { // 模拟复杂的算法计算 await Task.Delay(_random.Next(50, 300)); // 根据产品类型和数量计算生产时间 var baseTime = order.Product switch { "电机" => 2.0, "齿轮" => 1.5, "轴承" => 3.0, _ => 2.0 }; return (int)(order.Quantity * baseTime); } [PerformanceMonitor("数据库保存")] private async Task SaveOrderToDatabaseAsync(Order order) { // 模拟数据库保存操作 await Task.Delay(_random.Next(100, 400)); _orders.Add(order); } private string GetAvailableEquipment(string product) { var equipmentOptions = product switch { "电机" => new[] { "电机生产线A", "电机生产线B" }, "齿轮" => new[] { "齿轮加工中心1", "齿轮加工中心2" }, "轴承" => new[] { "轴承装配线1", "轴承装配线2" }, _ => new[] { "通用生产线1", "通用生产线2" } }; return equipmentOptions[_random.Next(equipmentOptions.Length)]; } public virtual async Task<List<Order>> GetOrdersAsync() { await Task.Delay(50); // 模拟数据库查询 return _orders.ToList(); } public virtual async Task<bool> UpdateOrderStatusAsync(string orderId, string status) { await Task.Delay(30); var order = _orders.FirstOrDefault(o => o.OrderId == orderId); if (order != null) { order.Status = status; return true; } return false; } } // 6. 生产调度服务 public interface IProductionScheduleService { Task<bool> CreateScheduleAsync(ProductionSchedule schedule); Task<List<ProductionSchedule>> GetSchedulesAsync(); } public class ProductionScheduleService : IProductionScheduleService { private readonly List<ProductionSchedule> _schedules; public ProductionScheduleService() { _schedules = new List<ProductionSchedule>(); } [PerformanceMonitor("创建生产调度")] public virtual async Task<bool> CreateScheduleAsync(ProductionSchedule schedule) { await Task.Delay(100); // 模拟调度算法计算 _schedules.Add(schedule); return true; } [PerformanceMonitor("获取调度列表")] public virtual async Task<List<ProductionSchedule>> GetSchedulesAsync() { await Task.Delay(50); return _schedules.ToList(); } } }

MainViewModel

C#
using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using ScottPlot.WPF; using ScottPlot; using System.Windows.Threading; using System.Windows; namespace AppIndustrialAop { public class MainViewModel : INotifyPropertyChanged { private readonly IOrderService _orderService; private readonly IProductionScheduleService _scheduleService; private readonly IPerformanceLogger _performanceLogger; private readonly DispatcherTimer _chartUpdateTimer; public ObservableCollection<Order> Orders { get; } public ObservableCollection<ProductionSchedule> Schedules { get; } public ObservableCollection<PerformanceRecord> PerformanceRecords { get; } // ScottPlot 图表相关 public WpfPlot ResponseTimeChart { get; private set; } public WpfPlot MethodStatsChart { get; private set; } public WpfPlot RequestCountChart { get; private set; } private string _newOrderId; private string _newCustomerName; private int _newQuantity; private string _newProduct; public string NewOrderId { get => _newOrderId; set { _newOrderId = value; OnPropertyChanged(); } } public string NewCustomerName { get => _newCustomerName; set { _newCustomerName = value; OnPropertyChanged(); } } public int NewQuantity { get => _newQuantity; set { _newQuantity = value; OnPropertyChanged(); } } public string NewProduct { get => _newProduct; set { _newProduct = value; OnPropertyChanged(); } } public List<string> ProductOptions { get; } = new List<string> { "电机", "齿轮", "轴承" }; public MainViewModel(IOrderService orderService, IProductionScheduleService scheduleService, IPerformanceLogger performanceLogger) { _orderService = orderService; _scheduleService = scheduleService; _performanceLogger = performanceLogger; Orders = new ObservableCollection<Order>(); Schedules = new ObservableCollection<ProductionSchedule>(); PerformanceRecords = _performanceLogger.GetPerformanceRecords(); // 初始化图表 InitializeCharts(); // 初始化默认值 NewOrderId = GenerateOrderId(); NewCustomerName = "客户A"; NewQuantity = 10; NewProduct = "电机"; // 启动图表更新定时器 _chartUpdateTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) }; _chartUpdateTimer.Tick += UpdateCharts; _chartUpdateTimer.Start(); } private void InitializeCharts() { // 响应时间图表 ResponseTimeChart = new WpfPlot(); ResponseTimeChart.Plot.Title("实时响应时间监控"); ResponseTimeChart.Plot.Axes.Left.Label.Text = "响应时间 (ms)"; ResponseTimeChart.Plot.Axes.Bottom.Label.Text = "时间"; ResponseTimeChart.Plot.Axes.Left.Min = 0; // 方法统计图表 MethodStatsChart = new WpfPlot(); MethodStatsChart.Plot.Title("方法性能统计"); MethodStatsChart.Plot.Axes.Left.Label.Text = "平均响应时间 (ms)"; MethodStatsChart.Plot.Axes.Bottom.Label.Text = "方法名"; // 请求计数图表 RequestCountChart = new WpfPlot(); RequestCountChart.Plot.Title("请求计数监控"); RequestCountChart.Plot.Axes.Left.Label.Text = "请求数量"; RequestCountChart.Plot.Axes.Bottom.Label.Text = "时间"; } private void UpdateCharts(object sender, EventArgs e) { UpdateResponseTimeChart(); UpdateMethodStatsChart(); UpdateRequestCountChart(); } private void UpdateResponseTimeChart() { var metrics = _performanceLogger.GetPerformanceMetrics(); if (!metrics.Any()) return; ResponseTimeChart.Plot.Clear(); ResponseTimeChart.Plot.Font.Set("SimSun"); var times = metrics.Select(m => m.Timestamp.ToOADate()).ToArray(); var responseTimes = metrics.Select(m => m.AverageResponseTime).ToArray(); var linePlot = ResponseTimeChart.Plot.Add.Scatter(times, responseTimes); linePlot.LineWidth = 2; linePlot.Color = Colors.Blue; linePlot.MarkerSize = 0; // 添加警告线 var warningLine = ResponseTimeChart.Plot.Add.HorizontalLine(500); warningLine.Color = Colors.Red; warningLine.LineWidth = 2; warningLine.LinePattern = LinePattern.Dashed; ResponseTimeChart.Plot.Axes.Bottom.TickGenerator = new ScottPlot.TickGenerators.DateTimeAutomatic(); ResponseTimeChart.Plot.Axes.AutoScale(); ResponseTimeChart.Refresh(); } private void UpdateMethodStatsChart() { var stats = _performanceLogger.GetMethodStats().Take(10).ToList(); if (!stats.Any()) return; MethodStatsChart.Plot.Clear(); MethodStatsChart.Plot.Font.Set("SimSun"); var positions = Enumerable.Range(0, stats.Count).Select(i => (double)i).ToArray(); var averageTimes = stats.Select(s => s.AverageTime).ToArray(); var labels = stats.Select(s => s.MethodName.Split('.').Last()).ToArray(); var barPlot = MethodStatsChart.Plot.Add.Bars(positions, averageTimes); barPlot.Color = Colors.Green; MethodStatsChart.Plot.Axes.Bottom.TickGenerator = new ScottPlot.TickGenerators.NumericManual(positions, labels); MethodStatsChart.Plot.Axes.Bottom.MajorTickStyle.Length = 0; MethodStatsChart.Plot.Axes.AutoScale(); MethodStatsChart.Refresh(); } private void UpdateRequestCountChart() { var metrics = _performanceLogger.GetPerformanceMetrics(); if (!metrics.Any()) return; RequestCountChart.Plot.Clear(); RequestCountChart.Plot.Font.Set("SimSun"); var times = metrics.Select(m => m.Timestamp.ToOADate()).ToArray(); var requestCounts = metrics.Select(m => (double)m.RequestCount).ToArray(); var barPlot = RequestCountChart.Plot.Add.Bars(times, requestCounts); barPlot.Color = Colors.Orange; RequestCountChart.Plot.Axes.Bottom.TickGenerator = new ScottPlot.TickGenerators.DateTimeAutomatic(); RequestCountChart.Plot.Axes.AutoScale(); RequestCountChart.Refresh(); } public async Task CreateOrderAsync() { var order = new Order { OrderId = NewOrderId, CustomerName = NewCustomerName, Quantity = NewQuantity, Product = NewProduct, OrderTime = DateTime.Now, Status = "处理中" }; try { var success = await _orderService.ProcessOrderAsync(order); if (success) { Orders.Add(order); await RefreshSchedulesAsync(); // 重置表单 NewOrderId = GenerateOrderId(); NewCustomerName = "客户A"; NewQuantity = 10; NewProduct = "电机"; } } catch (Exception ex) { MessageBox.Show($"创建订单失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } } public async Task RefreshSchedulesAsync() { var schedules = await _scheduleService.GetSchedulesAsync(); Schedules.Clear(); foreach (var schedule in schedules) { Schedules.Add(schedule); } } private string GenerateOrderId() { return $"ORD{DateTime.Now:yyyyMMddHHmmss}{new Random().Next(100, 999)}"; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }

🔧 依赖注入配置

🎯 关键:代理服务注册

C#
private void ConfigureServices(ServiceCollection services) { // 注册性能监控组件 services.AddSingleton<IPerformanceLogger, PerformanceLogger>(); services.AddSingleton<PerformanceInterceptor>(); services.AddSingleton<ProxyGenerator>(); // 🔥 核心:使用代理包装业务服务 services.AddSingleton<IOrderService>(provider => { var proxyGenerator = provider.GetRequiredService<ProxyGenerator>(); var interceptor = provider.GetRequiredService<PerformanceInterceptor>(); var scheduleService = provider.GetRequiredService<IProductionScheduleService>(); var target = new OrderService(scheduleService); return proxyGenerator.CreateInterfaceProxyWithTarget<IOrderService>(target, interceptor); }); services.AddSingleton<IProductionScheduleService>(provider => { var proxyGenerator = provider.GetRequiredService<ProxyGenerator>(); var interceptor = provider.GetRequiredService<PerformanceInterceptor>(); var target = new ProductionScheduleService(); return proxyGenerator.CreateInterfaceProxyWithTarget<IProductionScheduleService>(target, interceptor); }); }

MainWindow

C#
using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using Castle.DynamicProxy; using Microsoft.Extensions.DependencyInjection; namespace AppIndustrialAop { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { private readonly MainViewModel _viewModel; public MainWindow() { InitializeComponent(); // 配置依赖注入 var services = new ServiceCollection(); ConfigureServices(services); var serviceProvider = services.BuildServiceProvider(); _viewModel = serviceProvider.GetRequiredService<MainViewModel>(); DataContext = _viewModel; // 设置图表到UI SetupCharts(); } private void ConfigureServices(ServiceCollection services) { // 注册性能监控日志 services.AddSingleton<IPerformanceLogger, PerformanceLogger>(); // 注册拦截器 services.AddSingleton<PerformanceInterceptor>(); // 注册代理生成器 services.AddSingleton<ProxyGenerator>(); // 注册业务服务(使用代理) services.AddSingleton<IOrderService>(provider => { var proxyGenerator = provider.GetRequiredService<ProxyGenerator>(); var interceptor = provider.GetRequiredService<PerformanceInterceptor>(); var scheduleService = provider.GetRequiredService<IProductionScheduleService>(); var target = new OrderService(scheduleService); return proxyGenerator.CreateInterfaceProxyWithTarget<IOrderService>(target, interceptor); }); services.AddSingleton<IProductionScheduleService>(provider => { var proxyGenerator = provider.GetRequiredService<ProxyGenerator>(); var interceptor = provider.GetRequiredService<PerformanceInterceptor>(); var target = new ProductionScheduleService(); return proxyGenerator.CreateInterfaceProxyWithTarget<IProductionScheduleService>(target, interceptor); }); // 注册ViewModel services.AddSingleton<MainViewModel>(); } private void SetupCharts() { if (ResponseTimeChartContainer != null) ResponseTimeChartContainer.Child = _viewModel.ResponseTimeChart; if (MethodStatsChartContainer != null) MethodStatsChartContainer.Child = _viewModel.MethodStatsChart; if (RequestCountChartContainer != null) RequestCountChartContainer.Child = _viewModel.RequestCountChart; } private async void CreateOrderButton_Click(object sender, RoutedEventArgs e) { await _viewModel.CreateOrderAsync(); } private async void RefreshButton_Click(object sender, RoutedEventArgs e) { await _viewModel.RefreshSchedulesAsync(); } } }

UI

XML
<Window x:Class="AppIndustrialAop.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:AppIndustrialAop" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!-- 标题栏 --> <Border Grid.Row="0" Background="#FF2196F3" Padding="10"> <TextBlock Text="🏭 工业管理系统 - ScottPlot 5.0 性能监控实战" FontSize="20" FontWeight="Bold" Foreground="White" HorizontalAlignment="Center"/> </Border> <!-- 主要内容 --> <TabControl Grid.Row="1" Margin="10"> <!-- 订单管理 --> <TabItem Header="📋 订单管理"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <!-- 创建订单表单 --> <GroupBox Grid.Row="0" Header="创建新订单" Margin="5"> <Grid Margin="10"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="Auto"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Grid.Column="0" Text="订单号:" VerticalAlignment="Center" Margin="0,0,10,0"/> <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding NewOrderId}" Margin="0,0,10,0"/> <TextBlock Grid.Row="0" Grid.Column="2" Text="客户:" VerticalAlignment="Center" Margin="0,0,10,0"/> <TextBox Grid.Row="0" Grid.Column="3" Text="{Binding NewCustomerName}" Margin="0,0,10,0"/> <TextBlock Grid.Row="1" Grid.Column="0" Text="产品:" VerticalAlignment="Center" Margin="0,10,10,0"/> <ComboBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding ProductOptions}" SelectedItem="{Binding NewProduct}" Margin="0,10,10,0"/> <TextBlock Grid.Row="1" Grid.Column="2" Text="数量:" VerticalAlignment="Center" Margin="0,10,10,0"/> <TextBox Grid.Row="1" Grid.Column="3" Text="{Binding NewQuantity}" Margin="0,10,10,0"/> <Button Grid.Row="1" Grid.Column="4" Content="创建订单" Click="CreateOrderButton_Click" Background="#FF4CAF50" Foreground="White" Padding="15,5" Margin="0,10,0,0"/> </Grid> </GroupBox> <!-- 订单列表 --> <DataGrid Grid.Row="1" ItemsSource="{Binding Orders}" AutoGenerateColumns="False" Margin="5" CanUserAddRows="False" CanUserDeleteRows="False"> <DataGrid.Columns> <DataGridTextColumn Header="订单号" Binding="{Binding OrderId}" Width="150"/> <DataGridTextColumn Header="客户" Binding="{Binding CustomerName}" Width="120"/> <DataGridTextColumn Header="产品" Binding="{Binding Product}" Width="100"/> <DataGridTextColumn Header="数量" Binding="{Binding Quantity}" Width="80"/> <DataGridTextColumn Header="下单时间" Binding="{Binding OrderTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="150"/> <DataGridTextColumn Header="状态" Binding="{Binding Status}" Width="100"/> </DataGrid.Columns> </DataGrid> </Grid> </TabItem> <!-- 生产调度 --> <TabItem Header="⚙️ 生产调度"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Button Grid.Row="0" Content="刷新调度" Click="RefreshButton_Click" HorizontalAlignment="Right" Margin="5" Padding="10,5" Background="#FF2196F3" Foreground="White"/> <DataGrid Grid.Row="1" ItemsSource="{Binding Schedules}" AutoGenerateColumns="False" Margin="5" CanUserAddRows="False" CanUserDeleteRows="False"> <DataGrid.Columns> <DataGridTextColumn Header="调度ID" Binding="{Binding ScheduleId}" Width="120"/> <DataGridTextColumn Header="订单号" Binding="{Binding OrderId}" Width="150"/> <DataGridTextColumn Header="设备" Binding="{Binding Equipment}" Width="150"/> <DataGridTextColumn Header="开始时间" Binding="{Binding StartTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="150"/> <DataGridTextColumn Header="结束时间" Binding="{Binding EndTime, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="150"/> <DataGridTextColumn Header="预计时长(小时)" Binding="{Binding EstimatedDuration}" Width="120"/> </DataGrid.Columns> </DataGrid> </Grid> </TabItem> <!-- 性能监控图表 --> <TabItem Header="📊 性能监控图表"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <!-- 响应时间图表 --> <GroupBox Grid.Row="0" Grid.Column="0" Header="实时响应时间" Margin="5"> <Border x:Name="ResponseTimeChartContainer" /> </GroupBox> <!-- 方法统计图表 --> <GroupBox Grid.Row="0" Grid.Column="1" Header="方法性能统计" Margin="5"> <Border x:Name="MethodStatsChartContainer" /> </GroupBox> <!-- 请求计数图表 --> <GroupBox Grid.Row="1" Grid.Column="0" Header="请求计数" Margin="5"> <Border x:Name="RequestCountChartContainer" /> </GroupBox> <!-- 性能记录表格 --> <GroupBox Grid.Row="1" Grid.Column="1" Header="性能记录" Margin="5"> <DataGrid ItemsSource="{Binding PerformanceRecords}" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False"> <DataGrid.Columns> <DataGridTextColumn Header="方法名" Binding="{Binding MethodName}" Width="150"/> <DataGridTextColumn Header="时间(ms)" Binding="{Binding ElapsedMilliseconds}" Width="80"/> <DataGridTextColumn Header="状态" Binding="{Binding Status}" Width="60"> <DataGridTextColumn.ElementStyle> <Style TargetType="TextBlock"> <Style.Triggers> <Trigger Property="Text" Value="警告"> <Setter Property="Foreground" Value="Red"/> <Setter Property="FontWeight" Value="Bold"/> </Trigger> <Trigger Property="Text" Value="正常"> <Setter Property="Foreground" Value="Green"/> </Trigger> </Style.Triggers> </Style> </DataGridTextColumn.ElementStyle> </DataGridTextColumn> </DataGrid.Columns> </DataGrid> </GroupBox> </Grid> </TabItem> <!-- 性能数据表格 --> <TabItem Header="📋 性能数据"> <DataGrid ItemsSource="{Binding PerformanceRecords}" AutoGenerateColumns="False" Margin="5" CanUserAddRows="False" CanUserDeleteRows="False"> <DataGrid.Columns> <DataGridTextColumn Header="方法名" Binding="{Binding MethodName}" Width="250"/> <DataGridTextColumn Header="执行时间(ms)" Binding="{Binding ElapsedMilliseconds}" Width="120"/> <DataGridTextColumn Header="时间戳" Binding="{Binding Timestamp, StringFormat=yyyy-MM-dd HH:mm:ss}" Width="150"/> <DataGridTextColumn Header="状态" Binding="{Binding Status}" Width="80"> <DataGridTextColumn.ElementStyle> <Style TargetType="TextBlock"> <Style.Triggers> <Trigger Property="Text" Value="警告"> <Setter Property="Foreground" Value="Red"/> <Setter Property="FontWeight" Value="Bold"/> </Trigger> <Trigger Property="Text" Value="正常"> <Setter Property="Foreground" Value="Green"/> </Trigger> </Style.Triggers> </Style> </DataGridTextColumn.ElementStyle> </DataGridTextColumn> </DataGrid.Columns> </DataGrid> </TabItem> </TabControl> </Grid> </Window>

image.png

image.png

image.png

image.png

📊 性能数据收集器

🎯 智能数据管理

C#
public class PerformanceLogger : IPerformanceLogger { private readonly ObservableCollection<PerformanceRecord> _performanceRecords; private readonly Dictionary<string, List<long>> _methodPerformanceHistory; private readonly object _lock = new object(); public void LogPerformance(string methodName, long elapsedMs) { lock (_lock) { // 📈 记录到历史数据 if (!_methodPerformanceHistory.ContainsKey(methodName)) { _methodPerformanceHistory[methodName] = new List<long>(); } _methodPerformanceHistory[methodName].Add(elapsedMs); // 🔄 保持最近500条记录(防止内存溢出) if (_methodPerformanceHistory[methodName].Count > 500) { _methodPerformanceHistory[methodName].RemoveAt(0); } } // 🔥 UI线程安全更新 Application.Current.Dispatcher.Invoke(() => { _performanceRecords.Add(new PerformanceRecord { MethodName = methodName, ElapsedMilliseconds = elapsedMs, Timestamp = DateTime.Now, Status = elapsedMs > 500 ? "警告" : "正常" }); if (_performanceRecords.Count > 1000) { _performanceRecords.RemoveAt(0); } }); } // 📊 统计指标计算 public List<MethodPerformanceStats> GetMethodStats() { lock (_lock) { var stats = new List<MethodPerformanceStats>(); foreach (var kvp in _methodPerformanceHistory) { var values = kvp.Value; if (values.Any()) { stats.Add(new MethodPerformanceStats { MethodName = kvp.Key, AverageTime = values.Average(), MinTime = values.Min(), MaxTime = values.Max(), CallCount = values.Count, P95Time = CalculatePercentile(values, 95), // 95百分位 P99Time = CalculatePercentile(values, 99) // 99百分位 }); } } return stats.OrderByDescending(s => s.AverageTime).ToList(); } } // 🎯 百分位计算 private double CalculatePercentile(List<long> values, int percentile) { var sorted = values.OrderBy(x => x).ToList(); int index = (int)Math.Ceiling(percentile / 100.0 * sorted.Count) - 1; return sorted[Math.Max(0, Math.Min(index, sorted.Count - 1))]; } }

🎨 可视化监控界面

📈 实时图表展示

C#
public class MainViewModel : INotifyPropertyChanged { private readonly DispatcherTimer _chartUpdateTimer; public MainViewModel(IOrderService orderService, IProductionScheduleService scheduleService, IPerformanceLogger performanceLogger) { _orderService = orderService; _scheduleService = scheduleService; _performanceLogger = performanceLogger; // 📊 初始化图表 InitializeCharts(); // ⏰ 启动实时更新(每2秒刷新一次) _chartUpdateTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) }; _chartUpdateTimer.Tick += UpdateCharts; _chartUpdateTimer.Start(); } private void UpdateResponseTimeChart() { var metrics = _performanceLogger.GetPerformanceMetrics(); if (!metrics.Any()) return; ResponseTimeChart.Plot.Clear(); var times = metrics.Select(m => m.Timestamp.ToOADate()).ToArray(); var responseTimes = metrics.Select(m => m.AverageResponseTime).ToArray(); var linePlot = ResponseTimeChart.Plot.Add.Scatter(times, responseTimes); linePlot.LineWidth = 2; linePlot.Color = Colors.Blue; // ⚠️ 添加警告线 var warningLine = ResponseTimeChart.Plot.Add.HorizontalLine(500); warningLine.Color = Colors.Red; warningLine.LinePattern = LinePattern.Dashed; ResponseTimeChart.Plot.Axes.AutoScale(); ResponseTimeChart.Refresh(); } }

🎯 实战效果展示

📊 监控数据类型

  1. 实时响应时间曲线:直观看到系统负载变化
  2. 方法性能统计:识别性能瓶颈
  3. 请求计数监控:了解系统并发情况
  4. 百分位数据:P95、P99性能指标

🔍 性能分析能力

  • 自动预警:超过500ms自动标记警告
  • 历史趋势:保存最近500次调用数据
  • 统计指标:平均值、最大值、最小值、百分位
  • 异常捕获:方法执行异常自动记录

💡 核心优势总结

🎯 技术优势

  • 零侵入:业务代码无需修改
  • 高性能:拦截器开销极小
  • 易扩展:可以轻松添加新的监控指标
  • 线程安全:支持高并发场景

🛠️ 实用技巧

  1. 虚方法要求:被监控的方法必须是virtual的
  2. 接口代理:优先使用接口代理方式
  3. 内存管理:及时清理历史数据避免内存泄漏
  4. UI更新:使用Dispatcher确保线程安全

🚀 扩展建议

📈 进阶功能

  1. 集成日志框架:结合NLog或Serilog
  2. 数据持久化:将性能数据保存到数据库
  3. 分布式监控:结合APM工具做全链路监控
  4. 自动化报警:集成钉钉、企业微信通知

🎯 最佳实践

  • 合理设置监控阈值
  • 定期清理历史数据
  • 重要方法单独监控
  • 结合业务指标分析

这套方案在实际项目中表现如何?有哪些踩坑经验?欢迎在评论区分享你的实战心得!

觉得这个方案对你有帮助的话,请点赞收藏并转发给更多需要的同行!让我们一起让C#应用跑得更快、更稳定!

相关信息

通过网盘分享的文件:AppIndustrialAop.zip 链接: https://pan.baidu.com/s/1gRnCgMGijllu9_dFQ7fZbw?pwd=durs 提取码: durs --来自百度网盘超级会员v9的分享

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!