Rendering performance drops on selection. When the selection is de-selected, all is restored. This is especially evident on roofs
Also, in version 24, the hardware acceleration section of the interface is removed and always set as software.
Revit 2023:
Revit 2024:
Are there changes planned on this issue?
Thank you for checking! Added this info to REVIT-206162 [IExternalEventHandler.Execute not triggered when roof selected].
I tested and the external event triggers normally, probably another plugin is forcing it to trigger or something.
I know this behavior happens when Revit is busy. If you have an IExternalCommand running until finish the ExternalEvent never gonna trigger only when the command ends and I guess when the first Idling event runs.
You could try to check if your Idling event is triggering normally or Regenerate the document in the command to force ExternalEvent to trigger or something.
You could try SetRaiseWithoutDelay in the Idling as well.
Idling is not invoked in the same way. Yes, You right Transaction restores the process and events continue to be called correctly
So, what can I tell the development team? Is the behaviour as expected after all, everything in order, no problem? Should I cancel the ticket?
If not, they ask for more clarification: they say: So, let me rephrase the problem: When a roof in the Revit sample project is selected, any IExternalEventHandler.Execute is blocked until the roof is de-selected. Right? I will do some investigation on this. Thanks for narrowing the scope!
... they were able to reproduce locally themselves now...
The devteam debugging result suggests that Revit is in transient element creation scope. Then, they reproduced the same issue when a simple wall is selected. They think this is a not a Roof specific problem. They need more time to find out the root cause. Meanwhile, could you help verify that IExternalEventHandler.Execute is not triggered when a wall is selected? Not the wall in the sample file, just create a new wall in an empty project. Thank you!
Thank you for confirming. Here is another devteam update:
I have reproduced the same issue on latest master build. It turns out to be a general problem with elements that have direct shape controls - Walls, Roofs, Mass. When a Roof/Wall/Mass with direct shape controls is selected, the external event is not valid anymore by the time we get inside the external event manager execute event method...
Dear Roman,
Surprise, surprise.
The development team spent a lot more time analysing and discussing REVIT-206162 [IExternalEventHandler.Execute not triggered when roof selected] and made an important observation:
I just realized what the user did is not as expected, so here is another update. Hope what I got so far provides some useful information.
After looking into the client code in revit_addin.zip, I found out they wrap the IExternalEventHandler into a custom class "ExternalEventHandler", and derive another class "ActionHandler" from it. By reading the information in the metadata of "Nice3point.Revit.Toolkit.External.ExternalEventHandler", the Revit API class "Autodesk.Revit.UI.ExternalEvent" is stored as a private member of ExternalEventHandler.
Then, in Command.cs, they creat a new ActionHandler object and raise an Action<UIApplication> inside an ExternalCommand.
That is probably where the problem comes from. When that external event is not executed immediately, it is disposed along with the disposal of the ActionHandler object. By the time Revit decides to execute the external event, the reference to that event is no longer valid. That is why the "wpEvent" is null.
As a conclusion, creating an external event and raising that event directly inside an external command is not an ideal way. I am not familiar with the initial design of the IExternalEventHandler and what is the ideal way, but based on my experience, it is better to hold the ExternalEvent object somewhere outside Revit. So I've created a sample project as a workaround. See WorkaroundDemo.mp4.
Basically I just created a winform (non-modal) that holds the external event object, so that the form won't get disposed after the command is executed. Then everything works correctly.
Here is the refined code (the ExternalEventHandler class did not change):
[Transaction(TransactionMode.Manual)]
public class ExternalEventTestCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
ExecuteEventHandler handler = new ExecuteEventHandler("test");
handler.ExecuteAction = new Action<UIApplication>(app =>
{
TaskDialog.Show("test", "external event executed");
Debug.WriteLine("external event executed");
});
ExternalEvent externalEvent = ExternalEvent.Create(handler);
ExternalEventForm form = new ExternalEventForm(externalEvent);
form.Show();
return Result.Succeeded;
}
}
Best regards,
Jeremy
Garbage collection in dotnet doesn't work like that. Although the "handler" object is created in the Execute method, it is still referenced when ExternalEvent.Create(this) is called. Also works great when the roof is de-selected. All the more, you can create a strong reference to the object by making the field static
public class Command : ExternalCommand
{
private static ActionEventHandler _handler;
public override void Execute()
{
_handler = new ActionEventHandler();
_handler.Raise(application =>
{
Debug.WriteLine($"External event handled: {DateTime.Now:HH:mm:ss}");
});
}
}
Dear Roman,
Thank you for the analysis and clarification.
So, the problem can be solved by modifying the action event implementation in the add-in code.
Accordingly, the development team have closed the issue as "By Design" and add:
Closing this as By Design. Workaround is provided. The analysis is correct. This is about the lifetime of the object `ExternalEvent`. If the object is made to live longer (when Revit is ready to call the event), then the event is executed fine. Another workaround is to make this object a static in `command` or `application`.
Thank you for raising this. I guess we should condense this discussion and explanation into a succinct and readable blog post, in case anybody else runs into similar issues in the future.
I wish you a wonderful weekend and happy Labour Day!
https://en.wikipedia.org/wiki/Labour_Day
Best regards,
Jeremy
Hi Jeremy,
The problem is not the object's lifetime, it has also been alive and invoked before, but after de-selection the roof 🙈 The garbage collector does not remove the object. And making it static does not solve the issue
"This is about the lifetime of the object" this is a fundamentally incorrect description of what is happening here
Development team please read this book https://prodotnetmemory.com/ and use the debugger if there is doubt, there is no confirmation in your description that the object is being deleted from memory, because this is not true
Happy Labour Day Jeremy!
Thank you for being in touch and supporting the dialogue, have a nice weekend
Here is an example of an object that still exists in memory and is only invoked when the selection is removed from the roof
So, does the problem persist? Should the ticket not be closed? The devteam says, this is the way it is designed, on purpose.
Yes, exactly, REVIT-206162 issue has not been resolved and is reproduced for me and several other people
But it seems to me it is better to focus on the REVIT-206157 it affects Revit as a whole and not only add-ins and heavily loads the Main thread
Can't find what you're looking for? Ask the community or share your knowledge.