Revit 2015 InternalException on CustomExporter with Linked Files

Revit 2015 InternalException on CustomExporter with Linked Files

pfk
Enthusiast Enthusiast
1,323 Views
6 Replies
Message 1 of 7

Revit 2015 InternalException on CustomExporter with Linked Files

pfk
Enthusiast
Enthusiast

CustomExporter.export is crashing on Revit 2015 when run in a spearate thread when there are linked files in the scene.  Works fine on Revit 2014.

 

The code to reproduce this is....

 

        public class MyExportContext2 : IExportContext
        {

            public MyExportContext2()
            {
            }

            public void OnPolymesh(PolymeshTopology node)
            {
            }

            public void OnMaterial(MaterialNode node)
            {
            }

            public void Finish()
            {
            }

            public bool IsCanceled()
            {
                return false;
            }

            public void OnDaylightPortal(DaylightPortalNode node)
            {
            }

            public void OnLight(LightNode node)
            {
            }

            public RenderNodeAction OnLinkBegin(LinkNode node)
            {
                return RenderNodeAction.Proceed;
            }

            public void OnLinkEnd(LinkNode node)
            {
            }

            public void OnRPC(RPCNode node)
            {
            }

            public RenderNodeAction OnViewBegin(ViewNode node)
            {
                return RenderNodeAction.Proceed;
            }

            public void OnViewEnd(ElementId elementId)
            {
            }

            public RenderNodeAction OnFaceBegin(FaceNode node)
            {
                return RenderNodeAction.Proceed;
            }

            public void OnFaceEnd(FaceNode node)
            {
            }

            public RenderNodeAction OnElementBegin(ElementId elementId)
            {
                return RenderNodeAction.Proceed;
            }

            public void OnElementEnd(ElementId elementId)
            {
            }

            public RenderNodeAction OnInstanceBegin(InstanceNode node)
            {
                return RenderNodeAction.Proceed;
            }

            public void OnInstanceEnd(InstanceNode node)
            {
            }

            public bool Start()
            {
                return true;
            }
        }

 and to call it....

       class MyEventHandler : IExternalEventHandler 
        {
            public void RunExporter()
            {
                MyExportContext2 m_ExportContext = null;
                m_ExportContext = new MyExportContext2();
                CustomExporter exporter = new CustomExporter(HostManager.GetCurrentDocument(), m_ExportContext);
                View3D m_ActiveView = HostManager.GetCurrentDocument().ActiveView as View3D;
                exporter.Export(m_ActiveView);
            }

            public void Execute(UIApplication a)
            {
                if (!HostManager.IsCurrentView3dPerspective())
                {
                    SelectViewForm f = new SelectViewForm();
                    f.ShowDialog();
                }

                Thread thread = new Thread(this.RunExporter);
                thread.Start();
            }
...etc

 Paul

0 Likes
1,324 Views
6 Replies
Replies (6)
Message 2 of 7

arnostlobel
Alumni
Alumni

Oh, now we can see the problem clear. Paul, Revit API must not be accessed from other than the main thread! We (in Revit) do not support invoking API methods from other thread. In fact, it is the main purpose of the External Event mechanism to allow external out-of-thread processing to access the Revit API on demand at semi-random times. The External Event allows the user to signal the event (and that is done in a thread-safe manner). Once an external event is signaled, Revit will pick it up when ready and will call the event;s handler back. In the handler the user can do whatever he or she wants as long as he/she stays on the same thread. Again, communicating with the API from an outside thread is prohibited.

 

I think we have out mystery explained. I sort of suspected something like this when I saw your first post in the other thread. I hinted you that it looked like you addressed the API illegally and recommended the External Event mechanism. However, when you posted that you refactored your code using External Events I thought the thread were under control. 

 

Thank you

 

Arnošt Löbel

Sr. Principal Engineer

Autodesk, Revit R&D

 

Arnošt Löbel
0 Likes
Message 3 of 7

pfk
Enthusiast
Enthusiast
This is very unfortunate news. These changes present immense difficulties
for my plugin. Converting the scene load call (CustomExporter) into an
ExternalEvent which is on the UI thread stops Revit crashing, however, an
ExternalEvent does not fire when the user is viewing a 3d perspective
window. So, the user cannot open the plugin rendering window for the Revit
perspective view they want to render whilst viewing that perspective view.
This is a impractical solution.

To re-iterate, the plugin works perfectly on Revit 2014. But at this stage
looks non-viable for Revit 2015 with the new limitations which have been
imposed.

Paul
0 Likes
Message 4 of 7

arnostlobel
Alumni
Alumni
Yes, that is unfortunate but correct: Revit does not reach out to external applications while a perspective view is active. External Events are not invoked and so isn’t anything else (external commands, events, etc.) That is a legacy limitation that has been in the Revit API since its inception. The reason for it is that, historically, most of the functions in Revit was disabled in perspective views, and the development team woried that by opening functions via the API we would have allowed workflows that had not really been covered by any tests. It is possible that this threat  does not have any merits anymore, the limitation is still in place, however, as R2015 goes. We have been talking about taking it out for R2016 (a tasks already exists for it,) but it remains to be seen if we actually do it.
 
That’s for the technical background in case you are interested to hear the details. As for the “newly imposed limitations” and “it’s working in 2014”, I would argue about that. The fact is that we have not imposed any limitation regarding either perspective views or accessing Revit from outside threads. It has never been possible to run the API while in perspective views. And we have always tried to make it clear that accessing Revit  from outside threads is not supported and definitely not recommended. (I myself had presentations about that very topic at two different AU events and on another DevCamp event, plus wrote some documentation that circles around.) The claim itself that “it works in 2014” needs to be taken cautiously. While I do not doubt it works on your machine and probably for some of your users as well, I can practically guarantee that accessing the Revit API will crash some users’ session eventually no matter what version of Revit they run – that fact is virtually certain.
 
There is a workaround for this limitation, albeit I must admit it is not very elegant. Perspective views (and any 3D views) can be exported using Custom Exporters, but the export must start when the perspective view is not the active view. I do realize that it is kind of silly, however, that is the limitation we have in place now. Sorry about that. 😞 I would suggest that the application that export views is added to Revit as an external command. That command would be disabled in perspective views similarly to other commands, thus it should be not very surprising for the end user. And when the user is able to invoked the command (in a different view), the application can present him or her with a list of views to be exported, which may contain perspective views as well.
Arnošt Löbel
0 Likes
Message 5 of 7

pfk
Enthusiast
Enthusiast
Firstly - I appreciate the time and effort you are putting into providing
info on this issue.

However, the outcome is that I have invested an incredible amount of time
in the plugin, which cannot be made to run viably in Revit 2015.

The plugin has never crashed Revit 2014 to my knowledge. I've have no
users reports of crashes, and have spent countless hours using the plugin,
and never had a crash.

When the plugin starts (in a 2d view), the plugin setup dialog opens, and
then the user opens the plugin rendering Viewport. At this stage, a 3d
perspective view is selected, and the plugin rendering Viewport tracks the
Revit 3d perspective view - moving as the user moves the Revit camera. If
the user then closes the plugin rendering Viewport, Revit is left in the 3d
perspective view - so under 2015 the user cannot then open the Viewport
again - they have to return back to a 2 view, then reselect the 3d view.

Whilst the above is a serious limitation, a far greater problem is that
when the user has the plugin rendering viewport open, and they decide they
want to fresh the rendering geometry (which they would do on Revit 2014
frequently), under Revit 2015 they cannot - because they are currently
viewing a 3d perspective view.

All the above working perfectly in Revit 2014 and never crashed.

Paul
0 Likes
Message 6 of 7

arnostlobel
Alumni
Alumni
Paul,
 
I have thought about this a lot; not just the problem you’d reported, but others such similar cases as well. The truth is probably harsh for some, I admit, but we simply cannot afford making sure that unsupported workflows work the same from a version to another. We, Revit developers and software architects reserve the right to improve and modify our software to the best benefit of users who use it the standard and supported way. Not only we do not recommend (and do no agree with) users to use unsupported workflows, such as calling to the API from work threads, but we also do not have such workflows covered by any of our regression tests, quite naturally I’d say. That is why, of course, we would not even notice when we add, by coincidence, a road-block to some of the unsupported work-flows. I’d hope all this what I am saying should be understood by a reasonable person particularly one that has some clues about how software development works. We have almost twenty thousand tests which we run several times a day to make sure we keep the quality of our software high. That’s to say we really are carefully watching we do not impose any new limitations and/or regressions by any of our incremental changes to Revit (although it does happen sometimes, unfortunately). Regression of unsupported features is not the focus of our quality goals in any way though and, like I stated already, we do not have any tests for it. 
 
As for the crashing or not crashing: Paul, you can swear to me that your app never crashes, and who knows, you may be the lucky one, but I bet you good money that I’d be able to write a perfectly legal Revit add-in (which would not use any nonstandard ways) that would either crash your application or would be crashed by it. Like I said, a crash is virtually guaranteed – it only depends on the number of customers you distribute your add-in to, and other addins those customers have installed on their respective computers with Revit.
 
However, even if no crash is actually experienced, there is still the problem of using wrong data by your add-in. You export 3D views, which is a process that may take minutes. During the export there may be other (legally working) applications running in Revit and Revit would allow them to run since Revit does not know about your application actively exporting. Now, those other applications are, naturally, allowed to modify the model your application is in the middle of exporting of. When that happens, assuming it does not crash either your or the other applications, your export would suddenly be exporting inconsistent data, since the model is not what it was when the export started.
 
So, even knowing I may hurt someone’s feelings and make one upset, I have to be firm about this: Revit does not support unsupported features and does not guarantee they will behave the same way from a version to the next.
 
However, we naturally want to improve on the features we have and that includes our API. The request for allowing the API be functional in perspective views has been logged many times and its resolution is, in my opinion, long overdue. I promise I will put my very strong word for it to happen in R2016 and I hope that limitation will be lifted.
 
Respectfully,
Arnošt Löbel
Message 7 of 7

Sydra7
Contributor
Contributor

I have a similar problem. This API change is not too good. A new thread divided transaction system would be a better idea than this.

Have a nice day!

David Schmidt

0 Likes