Question

The API doesn't officially support threading (see below) or a way to close an active document. That said, a work around to closing an active document is to call...

SendKeys.SendWait("^{F4}");

...from a separate thread. That works fine, except I need to loop through opening and closing several documents. If I put any code at all after thread, it will run it before closing the previous document. I have tried a number of standard threading callback methods including...

Task.Factory.StartNew(() =>

ThreadPool.QueueUserWorkItem(new WaitCallback

AutoResetEvent.WaitOne()

with no luck. And Thread.Sleep() just stalls the error/crash. Does anyone have any ideas.

"Revit's internals make use of multiprocessing in only a few select isolated locations. None of these locations currently encompass the code in the Revit API, or any part of it. Thus Autodesk does not recommend making any calls to the Revit API from within simultaneously executing parallel threads. It may be that some part of the Revit API is isolated enough to be able to execute successfully from within such threading code in a test environment; this should not be taken to be a guarantee that the same source code will function for any model or situation, or that a future change in Revit will not cause this code to cease to function."

    public void OpenFile()
    {
        for (int i = 0; i < 3; i++)
        {
            uiApp.OpenAndActivateDocument(TargetPath(i));

            ThreadPool.QueueUserWorkItem(CloseDocProc);

            //any code here at all opens the next doc without closing the last
        }            
    }

    public void CloseDocProc(object stateInfo)
    {
        SendKeys.SendWait("^{F4}");

        //can run code here
    }
Was it helpful?

Solution

The problem was the threading, just like they said. Using any of the callback methods it would freeze right at that point. And you can only do a limited number of things in the thread, it would not let me open a document, no matter what!

The answer was to use a single-threaded timer.

System.Windows.Forms.Timer;

calling my Open() method every 10 seconds or so and stopping the timer and running the last bit of code when a counter reached a certain point.

OTHER TIPS

Not sure if it could do the trick, but you can perhaps use this technique: http://adndevblog.typepad.com/autocad/2012/06/use-thread-for-background-processing.html

It's for AutoCAD, but I think it could work with Revit. Revit API, like the AutoCAD one, do not support multithreading. You should only call the API functions from the main thread.

You need if fact to marshal the call to the main thread. The simplest way to achieve that is creating a System.Windows.Forms.Control object on the main thread and call its Invoke() from the separate thread where you're closing the document.

Or you can also use the Idle Event in a creative way...

Create a state machine in your app idle event handler that interacts with your thread and which handles the revit calls.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top