Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Avoiding side effects when running long-running scripts

bloudraak
Enthusiast

Avoiding side effects when running long-running scripts

bloudraak
Enthusiast
Enthusiast

I have a script that generates 100+ designs in Fusion 360. I'm able to reduce the issue to the following.

import adsk.core, adsk.fusion, adsk.cam, traceback, time

app: adsk.core.Application = None
ui = adsk.core.UserInterface.cast(None)

def run(context):
    global app
    global ui
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        project: adsk.core.DataProject = app.data.activeProject
        folder = get_folder(project.rootFolder, "Folder1")

        for n in range(1,1000):
            adsk.doEvents()
            name = 'Document{}'.format(n)
            app.log(f'Creating document {name}.')
            document = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
            # TODO: Fill the gap
            document.saveAs(name, folder, '', '')
            wait_until_saved(document)
            document.close(False)

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def wait_until_saved(document):
    start_time = time.time()
    end_time = start_time + 10
    while not document.dataFile.isComplete and time.time() < end_time:
        app.log('Waiting for save to finish.')
        time.sleep(0.5)
        adsk.doEvents()
    app.log("Done")

def create_sub_folder(parent: adsk.core.DataFolder, name: str) -> adsk.core.DataFolder:
    return parent and parent.dataFolders.add(name) or None

def get_folder(parent: adsk.core.DataFolder, name: str, create=True) -> adsk.core.DataFolder:
    folders = parent and parent.dataFolders
    folder = folders and folders.itemByName(name)
    folder = folder or create and create_sub_folder(parent, name) or None
    return folder

 

The challenge with this approach running Fusion 360 on macOS Monterey 12.1, is that despite Fusion 360 being full screen on one desktop, it will display this on the desktop you're working on, which in turn interferes with say reading this forum in a browser. 

 

wernersLNPQD_0-1642780713809.png

 

I have also found Fusion 360 to become unresponsive, and then subsequently crash even though the script has long been completed. I suspect the application may run out of memory if one doesn't close the documents.

 

What's the best approach to give Fusion 360 a fighting chance and avoid the display issues while the script is running.

 

I suspect the "time.Sleep" may block the UI. Perhaps it may be better for Fusion 360 to implement a sleep function on the app [app.Sleep(0.5)], or add some wait methods for long-running operations [e.g. doc.WaitToComplete() or doc.Sync()], or allow a script to run in its own background thread (which is what I did when I wrote software for OS/2 and Windows back in the day).  I've coded a bit in .NET and love the await pattern the platform provides for async development. 

  

 

Software Engineer
https://wernerstrydom.com
0 Likes
Reply
286 Views
2 Replies
Replies (2)

BrianEkins
Mentor
Mentor

Most of Fusion is running in a single thread. There are exceptions where it will run some things in a separate thread but most of it runs in the main thread, including the API. If you try using the API from a separate thread, you will run into problems.

 

You can see the effects of running in a single thread when a program runs because the UI doesn't update until the program has completed. This is because the program has taken over the main thread and Fusion doesn't have a chance to handle any pending messages. The adsk.doEvents() turns control back to Fusion to allow it to process pending messages and then the program continues running. You're also correct that calling the sleep function is blocking the UI and in fact is blocking all of Fusion. This is because you're program is halted during the sleep but it has control of the main thread so nothing else can happen. A sleep in this particular case works because we're waiting for something to finish on the cloud and blocking the Fusion thread doesn't impact that process. The sleep isn't needed and just reduces the number of lines written to log.

 

I don't have any comments regarding how Fusion behaves relative to other windows on the system because I don't know what the behavior is and it's not something that the API has any control over. I'm not saying you shouldn't be doing what you are doing because it is a reasonable use of the API, but Fusion itself is not tested in this way so you're pushing it beyond what it expects.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes

bloudraak
Enthusiast
Enthusiast

I opened a support case with Autodesk -- something is amiss on macOS.

 

Having written numerous applications across platforms myself, I understand why Fusion 360 behaves the way it does. There are a few other solutions, but none are really trivial, and this forum probably isn't the right place to discuss them.

 

Having written APIs myself, and having others consume them, it really isn't that far-fetched for a human to automate everything they would do manually using the UI, even if it runs for 20 minutes. That's all I'm doing here. 

 

The support to async activities within the Fusion 360 APIs is haphazard, to say the least. With so many activities being async, surely the complexity of saving a document and waiting for it to be available to use an assembly should be encapsulated within the API. Or when one creates a folder, and immediately wants to create a document therein. Or any operation that one can't guarantee to be completed in a reasonable amount of time (from experience that's about 0.2s). 

Software Engineer
https://wernerstrydom.com
1 Like