Tiempo de lectura: ~ 4 minutos
# Revit
# API
# C#
Actualizado 10 de marzo de 2025
En Autodesk Revit, la API está diseñada para ejecutarse en un único hilo principal. Esto significa que todas las modificaciones en el documento deben hacerse en el contexto de la API de Revit, es decir, en el hilo principal de Revit.
Sin embargo, hay situaciones en las que es útil realizar operaciones en segundo plano (por ejemplo, llamadas a APIs, cálculos intensivos, etc.). Para esto, se pueden crear hilos secundarios que no modifiquen directamente el documento.
Revit es una aplicación basada en un bucle de eventos y no es un programa de múltiples hilos en su núcleo. Cuando intentas modificar el documento desde otro hilo, Revit no puede garantizar la sincronización adecuada, lo que puede provocar errores o inestabilidad.
💡 Ejemplo de error común al modificar Revit desde un hilo secundario:
1"Starting a transaction from an external application running outside of API context is not allowed"
Esto ocurre porque la API está protegiendo la integridad del documento.
Para ejecutar código en segundo plano en Revit, se puede usar:
Ejemplo 1: Crear un hilo con Task.Run()
Si necesitas hacer una operación en segundo plano (pero sin modificar Revit), usa Task.Run():
1using System; 2using System.Threading.Tasks; 3using Autodesk.Revit.Attributes; 4using Autodesk.Revit.DB; 5using Autodesk.Revit.UI; 6 7[Transaction(TransactionMode.Manual)] 8public class AsyncExample : IExternalCommand 9{ 10 public Result Execute(ExternalCommandData commandData, 11 ref string message, 12 ElementSet elements) 13 { 14 // Inicia un hilo en segundo plano 15 Task.Run(() => 16 { 17 Task.Delay(3000).Wait(); // Simula una espera de 3 segundos 18 TaskDialog.Show("Hilo Secundario", "Este mensaje se ejecuta en un hilo diferente."); 19 }); 20 21 TaskDialog.Show("Hilo Principal", "Este mensaje se ejecuta en el hilo principal de Revit."); 22 return Result.Succeeded; 23 } 24}
🔹 Salida esperada:
Si necesitas hacer cálculos en un hilo secundario y luego modificar el documento de Revit, debes usar ExternalEvent.
Ejemplo 2: Crear un ExternalEvent para modificar Revit
Este es el método recomendado cuando necesitas combinar operaciones en segundo plano con modificaciones en Revit:
Crea un IExternalEventHandler para modificar Revit. Ejecuta una tarea en Task.Run() para llamar una API u otros procesos pesados. Llama a _externalEvent.Raise() desde el hilo secundario para ejecutar la transacción en Revit.
1using System; 2using System.Diagnostics; 3using System.Threading.Tasks; 4using Autodesk.Revit.Attributes; 5using Autodesk.Revit.DB; 6using Autodesk.Revit.UI; 7 8[Transaction(TransactionMode.Manual)] 9public class AsyncWithRevit : IExternalCommand 10{ 11 private static readonly MyExternalEventHandler _handler = new MyExternalEventHandler(); 12 private static readonly ExternalEvent _externalEvent = ExternalEvent.Create(_handler); 13 14 public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) 15 { 16 Task.Run(() => 17 { 18 Debug.WriteLine("Ejecutando operación en segundo plano..."); 19 20 Task.Delay(2000).Wait(); // Simula una espera de 2 segundos 21 22 Debug.WriteLine("Listo. Llamando a Revit para modificar el documento..."); 23 24 _externalEvent.Raise(); // Esto ejecutará el código en Revit 25 }); 26 27 return Result.Succeeded; 28 } 29} 30 31/// <summary> 32/// Este manejador ejecutará código en el contexto de Revit. 33/// </summary> 34public class MyExternalEventHandler : IExternalEventHandler 35{ 36 public void Execute(UIApplication app) 37 { 38 Document doc = app.ActiveUIDocument.Document; 39 40 using (Transaction trans = new Transaction(doc, "Crear Elemento")) 41 { 42 trans.Start(); 43 44 // Crear un texto de anotación como ejemplo 45 TextNote.Create(doc, doc.ActiveView.Id, new XYZ(0, 0, 0), "Texto creado desde un hilo secundario", new TextNoteType().Id); 46 47 trans.Commit(); 48 } 49 } 50 51 public string GetName() => "MyExternalEventHandler"; 52}
📌 Explicación
💡 Este método es seguro y evita errores de modificación del documento en hilos secundarios.
Caso | ¿Se puede hacer en un hilo secundario? | Método recomendado |
---|---|---|
Consultar una API externa | ✅ Sí | Task.Run() |
Realizar cálculos matemáticos pesados | ✅ Sí | Task.Run() |
Actualizar la UI (WPF/WinForms) | ⚠️ Depende | Dispatcher.Invoke() |
Modificar elementos en Revit | ❌ No | ExternalEvent |
Recibe semanalmente tutoriales, recursos, noticias sobre temas innovadores dentro del sector construcción y destaca profesionalmente.