"你的C#应用慢得像老牛拉车?用户投诉系统卡顿?"
在工业管理系统中,性能问题往往是致命的。一个订单处理慢了几秒钟,可能就是几万块的损失。传统的性能监控方案要么侵入性太强,要么监控不够细致。
今天,我们用一个真实的工业订单管理系统来演示如何通过AOP(面向切面编程)+ Castle.DynamicProxy实现零侵入的性能监控,让你的系统性能一目了然!
C#// 传统方式:代码侵入性强,维护困难
public async Task<bool> ProcessOrderAsync(Order order)
{
var stopwatch = Stopwatch.StartNew(); // 手动插入
try
{
// 业务逻辑
await DoBusinessLogic(order);
return true;
}
finally
{
stopwatch.Stop();
LogPerformance(stopwatch.ElapsedMilliseconds); // 手动插入
}
}
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();
}
}
}
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);
});
}
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();
}
}
}
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>
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();
}
}
这套方案在实际项目中表现如何?有哪些踩坑经验?欢迎在评论区分享你的实战心得!
觉得这个方案对你有帮助的话,请点赞收藏并转发给更多需要的同行!让我们一起让C#应用跑得更快、更稳定!
相关信息
通过网盘分享的文件:AppIndustrialAop.zip 链接: https://pan.baidu.com/s/1gRnCgMGijllu9_dFQ7fZbw?pwd=durs 提取码: durs --来自百度网盘超级会员v9的分享
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!