120 lines
5.0 KiB
Markdown
120 lines
5.0 KiB
Markdown
# Threading Optimization Summary for CtrEditor MCP Stability
|
|
|
|
## Problem
|
|
CtrEditor's MCP server was experiencing freezing issues during simulations due to blocking `Application.Current.Dispatcher.Invoke()` calls from background threads. This caused timeouts and made remote control via MCP unreliable during intensive simulations.
|
|
|
|
## Root Cause Analysis
|
|
The issue was caused by multiple high-frequency timer callbacks using synchronous `Dispatcher.Invoke()` calls:
|
|
1. `OnTickSimulacion()` - Main simulation timer (15ms intervals)
|
|
2. `OnRefreshEvent()` - PLC update timer (10ms intervals)
|
|
3. `TimerCallback()` in osBase.cs - Object movement timers
|
|
4. `TimerCallbackRemoveHighlight()` in ObjectManipulationManager.cs - UI highlight removal
|
|
|
|
## Threading Optimization Strategy
|
|
Replaced all blocking `Dispatcher.Invoke()` calls with non-blocking `Dispatcher.BeginInvoke()` calls using:
|
|
- **Background priority** to avoid blocking MCP operations
|
|
- **Comprehensive error handling** to prevent timer crashes
|
|
- **Dispatcher availability checks** to handle shutdown scenarios gracefully
|
|
|
|
## Files Modified
|
|
|
|
### 1. MainViewModel.cs
|
|
**OnTickSimulacion() method (lines ~1384-1410)**
|
|
- Changed from `Invoke()` to `BeginInvoke()` with Background priority
|
|
- Added Application.Current and Dispatcher availability checks
|
|
- Added try-catch with debug logging
|
|
|
|
**OnRefreshEvent() method (lines ~1399-1450)**
|
|
- Changed from `Invoke()` to `BeginInvoke()` with Background priority
|
|
- Added Application.Current and Dispatcher availability checks
|
|
- Added try-catch with debug logging
|
|
|
|
### 2. ObjetosSim/osBase.cs
|
|
**TimerCallback() method (lines ~937-961)**
|
|
- Changed from `Invoke()` to `BeginInvoke()` with Background priority
|
|
- Added Application.Current and Dispatcher availability checks
|
|
- Added try-catch with debug logging
|
|
- Added `using System.Windows.Threading;` for DispatcherPriority
|
|
|
|
### 3. ObjectManipulationManager.cs
|
|
**TimerCallbackRemoveHighlight() method (lines ~974-995)**
|
|
- Changed from `Invoke()` to `BeginInvoke()` with Background priority
|
|
- Added Application.Current and Dispatcher availability checks
|
|
- Added try-catch with debug logging
|
|
- Added `using System.Windows.Threading;` for DispatcherPriority
|
|
|
|
### 4. Services/MCPServer.cs (Previously Optimized)
|
|
- Already using `InvokeAsync()` with timeouts
|
|
- Added `IsDispatcherAvailable()` and `SafeDispatcherInvokeAsync()` methods
|
|
- Enhanced debug logging
|
|
|
|
## Testing Results
|
|
|
|
### Before Optimization
|
|
- MCP server would freeze during simulations
|
|
- `Application.Current.Dispatcher.Invoke()` calls blocked background threads
|
|
- Frequent "CtrEditor not available" errors during intensive operations
|
|
|
|
### After Optimization
|
|
- ✅ CtrEditor starts successfully with MCP responding
|
|
- ✅ Basic MCP operations work without freezing
|
|
- ✅ Simulation starts without blocking MCP server
|
|
- ✅ Build successful with all optimizations
|
|
|
|
### TSNet Test Setup Verified
|
|
The existing project contains the requested test setup:
|
|
- **2 Tanks**: "Tanque Origen" (source) and "Tanque Destino" (destination)
|
|
- **1 Pump**: "Bomba Principal" configured and running
|
|
- **3 Pipes**: "Tubería Entrada", "Tubería Intermedia", "Tubería Principal"
|
|
- **Hydraulic Network**: Properly connected in sequence for fluid flow
|
|
|
|
## Technical Implementation Details
|
|
|
|
### Threading Pattern Applied
|
|
```csharp
|
|
// BEFORE (blocking)
|
|
Application.Current.Dispatcher.Invoke(() => {
|
|
// UI updates
|
|
});
|
|
|
|
// AFTER (non-blocking)
|
|
if (Application.Current == null) return;
|
|
if (Application.Current.Dispatcher == null || Application.Current.Dispatcher.HasShutdownStarted)
|
|
return;
|
|
|
|
Application.Current.Dispatcher.BeginInvoke(new Action(() => {
|
|
try {
|
|
// UI updates
|
|
}
|
|
catch (Exception ex) {
|
|
Debug.WriteLine($"Error in [MethodName]: {ex.Message}");
|
|
}
|
|
}), DispatcherPriority.Background);
|
|
```
|
|
|
|
### Key Benefits
|
|
1. **Non-blocking execution**: Background threads don't wait for UI thread
|
|
2. **MCP stability**: Remote control operations remain responsive
|
|
3. **Error resilience**: Timer exceptions don't crash the application
|
|
4. **Graceful shutdown**: Proper checks for application lifecycle
|
|
|
|
## Remaining Considerations
|
|
- WaitForUIUpdateAsync() in MainViewModel.cs still uses sync Invoke() - this is intentional for UI synchronization in non-critical paths
|
|
- MatrixPreviewViewModel.cs has some Dispatcher.Invoke() calls - these are in user-initiated operations, not high-frequency timers
|
|
- Monitor simulation performance during extended runs to ensure optimization effectiveness
|
|
|
|
## Verification Commands
|
|
```bash
|
|
# Build verification
|
|
dotnet build CtrEditor.sln
|
|
|
|
# Search for remaining blocking calls
|
|
grep -r "Dispatcher\.Invoke(" --include="*.cs" .
|
|
|
|
# MCP testing
|
|
# Start CtrEditor -> list_objects -> start_simulation -> monitor status
|
|
```
|
|
|
|
## Impact Assessment
|
|
This optimization significantly improves MCP stability during simulations while maintaining all existing functionality. The non-blocking approach ensures that high-frequency simulation timers don't interfere with remote control operations, making CtrEditor much more reliable for automated testing and monitoring scenarios.
|