diff --git a/Samples/WindowsML/cs-wpf/MainWindow.xaml b/Samples/WindowsML/cs-wpf/MainWindow.xaml
index 66aac58fa..37564f094 100644
--- a/Samples/WindowsML/cs-wpf/MainWindow.xaml
+++ b/Samples/WindowsML/cs-wpf/MainWindow.xaml
@@ -62,6 +62,10 @@
+
+
+
diff --git a/Samples/WindowsML/cs-wpf/MainWindow.xaml.cs b/Samples/WindowsML/cs-wpf/MainWindow.xaml.cs
index dbd720ef1..7d797fbf9 100644
--- a/Samples/WindowsML/cs-wpf/MainWindow.xaml.cs
+++ b/Samples/WindowsML/cs-wpf/MainWindow.xaml.cs
@@ -26,14 +26,27 @@ public partial class MainWindow : Window, IDisposable
private OrtEnv? _ortEnv;
private List _labels = new();
private bool _disposed;
+ private bool _isBusy;
+ private bool _deviceComboWasEnabled;
+ private bool _epComboWasEnabled;
public MainWindow()
{
InitializeComponent(); // Must match x:Class in XAML
Loaded += MainWindow_Loaded;
+ Closing += MainWindow_Closing;
Closed += MainWindow_Closed;
}
+ private void MainWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e)
+ {
+ if (_isBusy)
+ {
+ e.Cancel = true;
+ ResultsTextBox.Text = "Please wait for the current operation to complete before closing.";
+ }
+ }
+
private void MainWindow_Closed(object? sender, EventArgs e)
{
Dispose();
@@ -133,11 +146,11 @@ private async Task LoadModelAndLabelsAsync()
{
ModelPath = "SqueezeNet.onnx",
EpName = EpCombo.SelectedItem?.ToString(),
- DeviceType = (DeviceCombo.IsEnabled ? DeviceCombo.SelectedItem?.ToString() : null),
+ DeviceType = (DeviceCombo.Items.Count > 1 ? DeviceCombo.SelectedItem?.ToString() : null),
PerfMode = GetSelectedPerformanceMode()
};
- if (DeviceCombo.IsEnabled && DeviceCombo.SelectedItem == null)
+ if (DeviceCombo.Items.Count > 1 && DeviceCombo.SelectedItem == null)
{
ResultsTextBox.Text = "Select a device type for the selected execution provider.";
return;
@@ -172,8 +185,10 @@ private void SelectImageButton_Click(object sender, RoutedEventArgs e)
bitmap.EndInit();
SelectedImage.Source = bitmap;
- RunInferenceButton.IsEnabled = true;
- ResultsTextBox.Text = "Image selected. Click 'Run Inference' to classify the image.";
+ RunInferenceButton.IsEnabled = _session != null;
+ ResultsTextBox.Text = _session != null
+ ? "Image selected. Click 'Run Inference' to classify the image."
+ : "Image selected. Load or reload the model first to enable inference.";
}
catch (Exception ex)
{
@@ -182,6 +197,34 @@ private void SelectImageButton_Click(object sender, RoutedEventArgs e)
}
}
+ private void SetBusy(bool busy)
+ {
+ _isBusy = busy;
+ BusyIndicator.Visibility = busy ? Visibility.Visible : Visibility.Collapsed;
+ RunInferenceButton.IsEnabled = !busy && _session != null && !string.IsNullOrEmpty(_selectedImagePath);
+ ReloadSessionButton.IsEnabled = !busy;
+ SelectImageButton.IsEnabled = !busy;
+ AllowProviderDownloadCheckBox.IsEnabled = !busy;
+ PerfModeDefaultRadio.IsEnabled = !busy;
+ PerfModeMaxPerfRadio.IsEnabled = !busy;
+ PerfModeMaxEffRadio.IsEnabled = !busy;
+
+ if (busy)
+ {
+ // Save combo states before disabling so we can restore them later
+ _epComboWasEnabled = EpCombo.IsEnabled;
+ _deviceComboWasEnabled = DeviceCombo.IsEnabled;
+ EpCombo.IsEnabled = false;
+ DeviceCombo.IsEnabled = false;
+ }
+ else
+ {
+ // Restore the combo enabled states that PopulateDeviceCombo computed
+ EpCombo.IsEnabled = _epComboWasEnabled;
+ DeviceCombo.IsEnabled = _deviceComboWasEnabled;
+ }
+ }
+
private async void RunInferenceButton_Click(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(_selectedImagePath) || _session == null)
@@ -192,14 +235,15 @@ private async void RunInferenceButton_Click(object sender, RoutedEventArgs e)
try
{
+ SetBusy(true);
ResultsTextBox.Text = "Running inference...";
- Dispatcher.Invoke(() => { }, System.Windows.Threading.DispatcherPriority.Render);
- var videoFrame = await ImageProcessor.LoadImageFileAsync(_selectedImagePath);
+ using var videoFrame = await ImageProcessor.LoadImageFileAsync(_selectedImagePath);
var inputTensor = await ImageProcessor.PreprocessImageAsync(videoFrame);
- using var results = InferenceEngine.RunInference(_session, inputTensor);
- var resultTensor = InferenceEngine.ExtractResults(_session, results);
+ var session = _session;
+ using var results = await Task.Run(() => InferenceEngine.RunInference(session, inputTensor));
+ var resultTensor = InferenceEngine.ExtractResults(session, results);
var topPredictions = ResultProcessor.GetTopPredictions(resultTensor, _labels, 5);
ResultsTextBox.Text = FormatResultsForUI(topPredictions);
@@ -208,6 +252,10 @@ private async void RunInferenceButton_Click(object sender, RoutedEventArgs e)
{
ResultsTextBox.Text = $"Error during inference: {ex.Message}";
}
+ finally
+ {
+ SetBusy(false);
+ }
}
private void PopulateDeviceCombo(OrtEnv env)
@@ -258,11 +306,23 @@ private void PopulateDeviceCombo(OrtEnv env)
private async void ReloadSessionButton_Click(object sender, RoutedEventArgs e)
{
- ResultsTextBox.Text = "Loading / reloading model...";
- await LoadModelAndLabelsAsync();
- if (_session != null)
+ try
+ {
+ SetBusy(true);
+ ResultsTextBox.Text = "Loading / reloading model...";
+ await LoadModelAndLabelsAsync();
+ if (_session != null)
+ {
+ ResultsTextBox.Text += "\nModel loaded. Select an image and click 'Run Inference'.";
+ }
+ }
+ catch (Exception ex)
+ {
+ ResultsTextBox.Text = $"Error loading model: {ex.Message}";
+ }
+ finally
{
- ResultsTextBox.Text += "\nModel loaded. Select an image and click 'Run Inference'.";
+ SetBusy(false);
}
}