Laservall_solidworks_inject/Windows/ResolvingProgressWindow.cs

106 lines
3.1 KiB
C#
Raw Permalink Normal View History

using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
namespace Laservall.Solidworks.Windows
{
/// <summary>
/// A progress dialog built entirely in code to avoid cross-thread XAML
/// parsing issues when shown on a dedicated STA thread (the WPF Application
/// instance lives on the main SolidWorks thread).
/// </summary>
public class ResolvingProgressWindow : Window
{
private readonly ManualResetEventSlim _rendered = new ManualResetEventSlim(false);
private ResolvingProgressWindow()
{
Title = "正在处理";
Width = 360;
Height = 140;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
WindowStyle = WindowStyle.ToolWindow;
ResizeMode = ResizeMode.NoResize;
Topmost = true;
ShowInTaskbar = false;
var label = new TextBlock
{
Text = "正在反轻化,请稍候...",
FontSize = 14,
HorizontalAlignment = HorizontalAlignment.Center,
Margin = new Thickness(0, 0, 0, 16)
};
var progressBar = new ProgressBar
{
Height = 20,
IsIndeterminate = true
};
var stack = new StackPanel { VerticalAlignment = VerticalAlignment.Center };
stack.Children.Add(label);
stack.Children.Add(progressBar);
var grid = new Grid { Margin = new Thickness(20) };
grid.Children.Add(stack);
Content = grid;
ContentRendered += (s, e) => _rendered.Set();
}
public static void RunWithProgress(Action action)
{
if (action == null) throw new ArgumentNullException(nameof(action));
Dispatcher windowDispatcher = null;
ManualResetEventSlim rendered = null;
var ready = new ManualResetEventSlim(false);
var uiThread = new Thread(() =>
{
try
{
var window = new ResolvingProgressWindow();
rendered = window._rendered;
windowDispatcher = window.Dispatcher;
ready.Set();
window.Show();
Dispatcher.Run();
}
catch
{
ready.Set();
}
});
uiThread.SetApartmentState(ApartmentState.STA);
uiThread.IsBackground = true;
uiThread.Name = "ResolvingProgressUI";
uiThread.Start();
ready.Wait();
// Wait for the window to fully render before starting the blocking action
if (rendered != null)
{
rendered.Wait(3000);
}
try
{
action();
}
finally
{
if (windowDispatcher != null)
{
windowDispatcher.InvokeShutdown();
}
}
}
}
}