311 lines
9.9 KiB
C#
311 lines
9.9 KiB
C#
// RevitHttpControl/App.cs
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Autodesk.Revit.Attributes;
|
|
using Autodesk.Revit.UI;
|
|
using Microsoft.Owin.Hosting;
|
|
using RevitHttpControl.Services;
|
|
|
|
namespace RevitHttpControl
|
|
{
|
|
/// <summary>
|
|
/// Revit 外部应用程序主类
|
|
/// </summary>
|
|
[Transaction(TransactionMode.Manual)]
|
|
public class App : IExternalApplication
|
|
{
|
|
/// <summary>
|
|
/// 应用程序单例实例
|
|
/// </summary>
|
|
public static App Instance { get; private set; }
|
|
|
|
private IDisposable _webApp;
|
|
private ExternalEvent _externalEvent;
|
|
private readonly ConcurrentQueue<Action<UIApplication>> _commandQueue = new ConcurrentQueue<Action<UIApplication>>();
|
|
private readonly CommandHandler _handler = new CommandHandler();
|
|
private CancellationTokenSource _cancellationTokenSource;
|
|
private Task _queueProcessorTask;
|
|
private readonly string _serverUrl = "http://localhost:9000";
|
|
|
|
/// <summary>
|
|
/// Revit 启动时调用
|
|
/// </summary>
|
|
/// <param name="app">UI 控制应用程序</param>
|
|
/// <returns>操作结果</returns>
|
|
public Result OnStartup(UIControlledApplication app)
|
|
{
|
|
try
|
|
{
|
|
Instance = this;
|
|
_cancellationTokenSource = new CancellationTokenSource();
|
|
|
|
// 创建外部事件
|
|
_externalEvent = ExternalEvent.Create(_handler);
|
|
|
|
// 启动HTTP服务器
|
|
StartWebServer();
|
|
|
|
// 启动命令队列处理器
|
|
StartQueueProcessor();
|
|
|
|
// 显示启动成功消息
|
|
TaskDialog.Show("RevitHttpControl",
|
|
$"HTTP 服务器已启动\n" +
|
|
$"地址: {_serverUrl}\n" +
|
|
$"健康检查: {_serverUrl}/api/health");
|
|
|
|
return Result.Succeeded;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
TaskDialog.Show("RevitHttpControl 启动失败",
|
|
$"启动HTTP服务器时发生错误:\n{ex.Message}\n\n详细信息:\n{ex}");
|
|
return Result.Failed;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 启动 Web 服务器
|
|
/// </summary>
|
|
private void StartWebServer()
|
|
{
|
|
try
|
|
{
|
|
_webApp = WebApp.Start<Startup>(_serverUrl);
|
|
System.Diagnostics.Debug.WriteLine($"RevitHttpControl: Web server started at {_serverUrl}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw new InvalidOperationException($"无法启动HTTP服务器在地址 {_serverUrl}", ex);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 启动命令队列处理器
|
|
/// </summary>
|
|
private void StartQueueProcessor()
|
|
{
|
|
_queueProcessorTask = Task.Run(async () =>
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("RevitHttpControl: Command queue processor started");
|
|
|
|
while (!_cancellationTokenSource.Token.IsCancellationRequested)
|
|
{
|
|
try
|
|
{
|
|
if (_commandQueue.TryDequeue(out var command))
|
|
{
|
|
_handler.SetCommand(command);
|
|
_externalEvent.Raise();
|
|
|
|
// 短暂等待让外部事件有时间执行
|
|
await Task.Delay(10, _cancellationTokenSource.Token);
|
|
}
|
|
else
|
|
{
|
|
// 队列为空时等待更长时间
|
|
await Task.Delay(50, _cancellationTokenSource.Token);
|
|
}
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
// 正常的取消操作,退出循环
|
|
break;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// 记录错误但继续运行
|
|
System.Diagnostics.Debug.WriteLine($"RevitHttpControl: Error in queue processor: {ex}");
|
|
await Task.Delay(1000, _cancellationTokenSource.Token);
|
|
}
|
|
}
|
|
|
|
System.Diagnostics.Debug.WriteLine("RevitHttpControl: Command queue processor stopped");
|
|
}, _cancellationTokenSource.Token);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 将命令添加到执行队列
|
|
/// </summary>
|
|
/// <param name="command">要执行的命令</param>
|
|
public void EnqueueCommand(Action<UIApplication> command)
|
|
{
|
|
if (command == null)
|
|
throw new ArgumentNullException(nameof(command));
|
|
|
|
if (_cancellationTokenSource?.Token.IsCancellationRequested == true)
|
|
{
|
|
throw new InvalidOperationException("应用程序正在关闭,无法添加新命令");
|
|
}
|
|
|
|
_commandQueue.Enqueue(command);
|
|
System.Diagnostics.Debug.WriteLine($"RevitHttpControl: Command enqueued, queue size: {_commandQueue.Count}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取队列状态信息
|
|
/// </summary>
|
|
/// <returns>队列状态</returns>
|
|
public QueueStatus GetQueueStatus()
|
|
{
|
|
return new QueueStatus
|
|
{
|
|
QueueSize = _commandQueue.Count,
|
|
IsProcessorRunning = _queueProcessorTask?.Status == TaskStatus.Running,
|
|
IsServerRunning = _webApp != null
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Revit 关闭时调用
|
|
/// </summary>
|
|
/// <param name="app">UI 控制应用程序</param>
|
|
/// <returns>操作结果</returns>
|
|
public Result OnShutdown(UIControlledApplication app)
|
|
{
|
|
try
|
|
{
|
|
System.Diagnostics.Debug.WriteLine("RevitHttpControl: Shutting down...");
|
|
|
|
// 停止队列处理器
|
|
StopQueueProcessor();
|
|
|
|
// 停止Web服务器
|
|
StopWebServer();
|
|
|
|
// 清理任务管理器
|
|
CleanupTaskManager();
|
|
|
|
System.Diagnostics.Debug.WriteLine("RevitHttpControl: Shutdown completed");
|
|
return Result.Succeeded;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"RevitHttpControl: Error during shutdown: {ex}");
|
|
return Result.Failed;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止命令队列处理器
|
|
/// </summary>
|
|
private void StopQueueProcessor()
|
|
{
|
|
try
|
|
{
|
|
_cancellationTokenSource?.Cancel();
|
|
_queueProcessorTask?.Wait(TimeSpan.FromSeconds(5));
|
|
_cancellationTokenSource?.Dispose();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"RevitHttpControl: Error stopping queue processor: {ex}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 停止Web服务器
|
|
/// </summary>
|
|
private void StopWebServer()
|
|
{
|
|
try
|
|
{
|
|
_webApp?.Dispose();
|
|
_webApp = null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"RevitHttpControl: Error stopping web server: {ex}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 清理任务管理器
|
|
/// </summary>
|
|
private void CleanupTaskManager()
|
|
{
|
|
try
|
|
{
|
|
TaskManager.Instance.CleanupExpiredTasks();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"RevitHttpControl: Error cleaning up task manager: {ex}");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 外部事件命令处理器
|
|
/// </summary>
|
|
public class CommandHandler : IExternalEventHandler
|
|
{
|
|
private Action<UIApplication> _command;
|
|
private readonly object _lock = new object();
|
|
|
|
/// <summary>
|
|
/// 设置要执行的命令
|
|
/// </summary>
|
|
/// <param name="command">命令</param>
|
|
public void SetCommand(Action<UIApplication> command)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
_command = command;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 执行命令
|
|
/// </summary>
|
|
/// <param name="app">UI应用程序</param>
|
|
public void Execute(UIApplication app)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
try
|
|
{
|
|
_command?.Invoke(app);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
System.Diagnostics.Debug.WriteLine($"RevitHttpControl: Error executing command: {ex}");
|
|
// 这里可以添加更详细的错误处理逻辑
|
|
}
|
|
finally
|
|
{
|
|
_command = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取处理器名称
|
|
/// </summary>
|
|
/// <returns>处理器名称</returns>
|
|
public string GetName() => "RevitHttpControl Command Handler";
|
|
}
|
|
|
|
/// <summary>
|
|
/// 队列状态信息
|
|
/// </summary>
|
|
public class QueueStatus
|
|
{
|
|
/// <summary>
|
|
/// 队列大小
|
|
/// </summary>
|
|
public int QueueSize { get; set; }
|
|
|
|
/// <summary>
|
|
/// 处理器是否正在运行
|
|
/// </summary>
|
|
public bool IsProcessorRunning { get; set; }
|
|
|
|
/// <summary>
|
|
/// 服务器是否正在运行
|
|
/// </summary>
|
|
public bool IsServerRunning { get; set; }
|
|
}
|
|
} |