using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Threading; namespace ShrlAlgo.Addin.Test { public static class ProgressManager { /// /// 启动带进度条的 Revit 主线程任务 /// /// 进度条窗口标题 /// 需要在 Revit 主线程执行的任务逻辑 public static void Run(string title, Action revitTask) { var cts = new CancellationTokenSource(); var viewModel = new ProgressViewModel(title, cts); var reporter = new ProgressReporter(viewModel); // 使用 ManualResetEvent 等待 WPF 窗口初始化完成 using (var viewReadyEvent = new ManualResetEvent(false)) { // 1. 创建独立的 STA 线程运行 WPF UI var uiThread = new Thread(() => { viewModel.UIDispatcher = Dispatcher.CurrentDispatcher; var window = new ProgressWindow(viewModel); window.Show(); viewReadyEvent.Set(); // 通知主线程 UI 已就绪 Dispatcher.Run(); // 开启消息循环 }); uiThread.SetApartmentState(ApartmentState.STA); // 必须是 STA uiThread.IsBackground = true; uiThread.Start(); viewReadyEvent.WaitOne(); // 阻塞主线程,直到 WPF 窗体显示 // 2. 在 Revit 主线程中执行耗时任务 try { revitTask(reporter, cts.Token); } catch (OperationCanceledException) { // 捕获取消异常,静默处理即可 } catch (Exception ex) { Autodesk.Revit.UI.TaskDialog.Show("Task Error", ex.Message); } finally { // 3. 任务结束,通知 WPF 线程关闭窗口并停止调度器 if (viewModel.UIDispatcher != null && !viewModel.UIDispatcher.HasShutdownStarted) { viewModel.UIDispatcher.InvokeAsync(() => { viewModel.CloseAction?.Invoke(); Dispatcher.CurrentDispatcher.InvokeShutdown(); }); } uiThread.Join(1000); // 等待 UI 线程彻底退出 cts.Dispose(); } } } } }