Hoy quiero profundizar en un tema que ha sido tanto desafiante como gratificante para mí: escribir plugins para Revit usando C#. Aunque desarrollo plugins para varias plataformas, Revit realmente me ha cautivado con su versatilidad, gracias en gran parte a la poderosa API desarrollada por Autodesk.
Si estás comenzando con el desarrollo de plugins de Revit, es probable que encuentres algunos obstáculos que no se resuelven fácilmente con una búsqueda rápida en línea.
El Desafío de las Operaciones Asíncronas en Revit
Un obstáculo común que podrías enfrentar es realizar operaciones asíncronas correctamente. Es crucial manejar estas operaciones apropiadamente para capturar cualquier excepción que pueda ocurrir. Para ayudar con esto, he escrito un código de extensión para gestionar Async/Await dentro de un solo hilo.
Entendiendo el Problema
La API de Revit opera en un modelo de un solo hilo, lo que significa que los patrones tradicionales async/await no funcionan como se espera. Cuando intentas usar código asíncrono estándar en Revit, puedes encontrar:
- Problemas de hilos
- Excepciones no manejadas
- Congelamiento de la UI
- Comportamiento inesperado
La Solución: Clase Auxiliar AsyncTasksExecutor
Aquí está cómo escribir una clase auxiliar para este propósito:
/// <summary>
/// Ayuda a realizar acciones asíncronas en Revit, porque Async no funciona en Revit
/// </summary>
public static class AsyncTasksExecutor
{
public static T Execute<T>(Func<Task<T>> action)
{
var task = Task.Run(action.Invoke);
return task.GetAwaiter().GetResult();
}
public static T Execute<T>(Func<ValueTask<T>> action)
{
var task = Task.Run(async() => await action());
return task.GetAwaiter().GetResult();
}
}
Cómo Funciona
La clase AsyncTasksExecutor proporciona dos métodos Execute sobrecargados:
- Para Task
- Maneja tareas asíncronas estándar que devuelven un valor - Para ValueTask
- Maneja tareas de valor para mejor rendimiento en ciertos escenarios
Ambos métodos usan Task.Run para ejecutar la operación asíncrona en un hilo del pool de hilos, luego esperan sincrónicamente el resultado usando GetAwaiter().GetResult(). Este enfoque asegura:
- Propagación apropiada de excepciones
- Compatibilidad con ejecución de un solo hilo
- Estructura de código limpia
Ejemplo Práctico
Aquí proporciono un ejemplo de cómo usar esta clase auxiliar en sus proyectos:
public void ShowHowExtensionWorks()
{
object yourObject = new object();
bool result = AsyncTasksExecutor.Execute(() => DoAsyncWorks(yourObject));
}
public async Task<bool> DoAsyncWorks(object someObjectsYouCanUse)
{
await Task.Delay(1000); // Simular operación asíncrona
return true;
}
Mejores Prácticas
Cuando uses este patrón en sus plugins de Revit:
- ✅ Siempre envuelve operaciones async con la clase auxiliar
- ✅ Maneja excepciones apropiadamente dentro de sus métodos async
- ✅ Mantén operaciones async ligeras para evitar bloqueo de UI
- ✅ Prueba exhaustivamente con diferentes escenarios
- ✅ Documenta su código async para mantenimiento futuro
Errores Comunes a Evitar
- ❌ No uses async/await directamente en callbacks de Revit API
- ❌ No crees operaciones de larga duración sin retroalimentación a usuarios
- ❌ No ignores el manejo de excepciones en métodos async
- ❌ No mezcles patrones síncronos y asíncronos inconsistentemente
Comparte Su Experiencia
Me encantaría escuchar sus pensamientos—si has tenido experiencia trabajando con llamadas asíncronas en la API de Revit, por favor comparte sus ideas en info@apibim.com.
¿Has encontrado otros desafíos con el desarrollo de plugins de Revit? ¿Hay patrones alternativos que hayas encontrado útiles? Su retroalimentación y experiencias pueden ayudar a que la comunidad crezca y aprenda junta.
Conclusión
Las operaciones asíncronas en Revit API no tienen que ser un obstáculo. Con la clase auxiliar correcta y comprensión de las restricciones de hilo único, puedes escribir código async limpio y mantenible que se integra perfectamente con la arquitectura de Revit. El patrón AsyncTasksExecutor proporciona una solución directa que maneja la complejidad mientras mantiene su código legible y seguro ante excepciones.
¡Feliz codificación, y que sus plugins de Revit sean poderosos y confiables!
