The Revit API provides an External Events framework to accommodate the use of modeless dialogs. It is tailored for asynchronous processing and operates similarly to the Idling event with default frequency.
You can look at the official document from Autodesk here : https://help.autodesk.com/view/RVT/2024/ENU/?guid=Revit_API_Revit_API_Developers_Guide_Advanced_Topics_External_Events_html
But we can use more simple than with Revit.Async
Use In IExternalCommand
- Dowload Library Revit.Async from package nuget API manager
<PackageReference Include="Revit.Async" Version="2.1.*" />
- Add Test Code:
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Revit.Async;
namespace UpdateAssemblyCodeAddIn;
[Transaction(TransactionMode.Manual)]
public class Command : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
var externalCommandData = commandData;
string zipFilePath = string.Empty;
RevitTask.Initialize(externalCommandData.Application);
RevitTask.RunAsync(async () =>
{
UIDocument uidoc = externalCommandData.Application.ActiveUIDocument;
Document doc = uidoc.Document;
await Task.Delay(1000);
});
return Result.Succeeded;
}
}
Use In ExternalEventHandler
public Result OnStartup(UIControlledApplication application)
{
UIApplication uiapp = application.GetUIApplication();
RevitTask.Initialize(uiApp);
return Result.Succeeded;
}
Some diffrence way to get UIApplication is can use a method follow with topic Revit API Forum
/// <summary>
/// Get <see cref="Autodesk.Revit.UI.UIApplication"/> using the <paramref name="application"/>
/// </summary>
/// <param name="application">Revit UIApplication</param>
public static UIApplication GetUIApplication(this UIControlledApplication application)
{
var type = typeof(UIControlledApplication);
var propertie = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
.FirstOrDefault(e => e.FieldType == typeof(UIApplication));
return propertie?.GetValue(application) as UIApplication;
}
Use In IExternalDBApplication
public Result OnStartup(UIControlledApplication application)
{
application.ControlledApplication.ApplicationInitialized += test;
return Result.Succeeded;
}
private void test(object sender, ApplicationInitializedEventArgs e)
{
if (sender is Application application)
{
var uiApp = new UIApplication(application);
RevitTask.Initialize(uiApp);
}
}
Use Await Async Revit Design Automation
You know that Revit Design Automation not allow you run with User Interface Add-in, so that could be a limit if you want run and use Await Async in code. That why you will see some meesage like Could not load file or assembly 'RevitAPIUI,....
[01/15/2025 06:01:03] Found an addIn for registration: DataSetParameter.addin
[01/15/2025 06:01:03] Language not specified, using English-United States(ENU) as default.
[01/15/2025 06:01:14] Get RCE: (VersionBuild) 24.2.10.64 (VersionNumber) 2024 (SubVersionNumber) 2024.2.10
[01/15/2025 06:01:16] System.IO.FileNotFoundException: Could not load file or assembly 'RevitAPIUI, Version=22.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
[01/15/2025 06:01:16] File name: 'RevitAPIUI, Version=22.0.0.0, Culture=neutral, PublicKeyToken=null'
[01/15/2025 06:01:16] at UpdateAssemblyCodeAddIn.App.DoJob(DesignAutomationReadyEventArgs e)
[01/15/2025 06:01:16] at UpdateAssemblyCodeAddIn.App.HandleDesignAutomationReadyEvent(Object sender, DesignAutomationReadyEventArgs e)
[01/15/2025 06:01:16] at DesignAutomationFramework.DesignAutomationBridge.RaiseDesignAutomationReadyEvent(DesignAutomationReadyEventArgs e)
Restrictions from Autodesk for Design Automation API for Revit
The Design Automation API for Revit imposes the following restrictions on your AppBundles, Activities, and Workitems:
- No access to Revit’s UI interfaces. Your application must be a RevitDB application only.
- Writing to the disk is restricted to Revit’s current working directory.
- There is no access to the ActiveView or ActiveDocument property for AppBundles that run on the Design Automation API for Revit.
- Export to Navisworks functionality is not available.
- Autodesk Desktop Connector is not supported.
Firewall Configuration for Callbacks
In order to process the onComplete
or onProgress
callback behind a firewall, the following IPs need to be allowed for Revit:
3.229.167.149
44.207.230.78
54.175.193.194
To work with Async/Task you need to force the Task to wait, I always use the GetAwaiter().GetResult() to convert something async to synchronous.
Here is a sample:
var task = Task.Run(async () =>
{
await Task.Delay(1000);
return "Task message";
});
var message = task.GetAwaiter().GetResult();
This works fine in Revit, but you cannot have any Revit API calls inside the Task to prevent RevitAddin context issues.
So what is best idea to can use Await/ Async is :
Design Code Revit API and Code for call some web api seperate function and call it.
Thank for reading the post, Cheers !
Top comments (0)