AMWorkflowController running should only be done from the main thread

I have a custom automator action that allows the user to select an automator workflow and run that workflow to process a list of files passed as input to the action. This action runs as expected on Sierra but fails with the following message on High Sierra and Mojave:


"AMWorkflowController running should only be done from the main thread!"


From correspondence with Apple Developer Technical Support, it is still unclear whether this is now expected behavior or a bug. Has anyone else run into this issue? Has anyone found a solution?


I am aware that Apple provides a "Run Workflow" automator action. Unfortunately, I need more granular control than this action provides.

Replies

Now that you’ve boiled this question down into this main thread issue it should be something that DTS supports. Someone should be in touch via that channel soon.

ps

AMWorkflowController
has always been a main-thread-only class; we added this check to catch folks who are using the it incorrectly. I, or one of my colleagues, should be able to help you figure out how you’ve doing that.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Now that you’ve boiled this question down into this main thread issue it should be something that DTS supports.

Hmmm, maybe not )-:

OK, let’s do this here. You wrote:

I have a custom automator action that allows the user to select an automator workflow and run that workflow to process a list of files passed as input to the action.

Can you boil this down into a simple test project that still triggers the issue?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Quinn,


This is about as simple of an example as I can provide:


An ApplescriptObjC automator action project in Xcode. The Interface builder provides an Automator Path Pop Up Button that allows the user to select an existing workflow to be run. The code to implement the action is shown below.


------------------------------ Applescript code for automator action ---------------------------------


script Run_Workflow_on_Each_Job -- this the File's Owner in IB

property parent : class "AMBundleAction"

property pWFController : missing value -- connected to AMWorkflowController instance in IB

property pWorkflow : missing value -- assigned here

property pWFView : missing value -- assigned here

property pWorkflowPath : "" -- posix path to workflow specified by user in GUI


on runWithInput_fromAction_error_(input, anAction, errorRef)

try

-- set up workflow

set paramRec to parameters() as record

set pWorkflowPath to |workflowPath| of paramRec

set wfURL to current application's NSURL's fileURLWithPath_isDirectory_(pWorkflowPath, false)

set myErr to current application's NSError's errorWithDomain_code_userInfo_(current application's NSCocoaErrorDomain, 1, {localizedDescription:"Error", code:0})

tell current application's AMWorkflow to set pWorkflow to alloc()'s initWithContentsOfURL_error_(wfURL, a reference to myErr)

if pWorkflow is missing value then

error "Could not initialize workflow"

end if

-- set up the controller

tell pWFController

setDelegate_(me)

setWorkflow_(pWorkflow)

setWorkflowView_(pWFView) -- this is hidden

end tell

set theJob to input

tell pWorkflow to setInput_(theJob)

tell pWFController

run_(me)

end tell


return input -- for test

on error errMsg number errNum

set contents of errorRef to {OSAScriptErrorNumberKey:errNum, OSAScriptErrorMessageKey:errMsg}

return missing value

end try

end runWithInput_fromAction_error_

end script


--------------------------------- end of sample code ----------------------------------


Thanks,

Steve

Thanks for that. I was making all sorts of assumptions about how your code was structured, and this makes it clear that I was off in the weeds.

The problematic line is this one:

run_(me)

In 10.13 we added a check to

-[AMWorkflowController run:]
to ensure that it’s called on the main thread. This has always been a requirement (the method is flagged as an
IBAction
, and IB actions are always main-thread-only), it’s just now being enforced.

The problem is that your Cocoa-AppleScript automator action is not calling it on the main thread. I’m not entirely sure why, but I think it’s related to the runtime environment of Cocoa-AppleScript automator actions. I encourage you to file a bug about that. AppleScript does not have any easy way to run code on a different thread, so if the system runs your Cocoa-AppleScript automator action on a secondary thread then there’s a whole bunch of of main-thread-only stuff that you can’t do.

Please post your bug number, just for the record.

I can see a few ways you might get around this:

  • You could abandon

    AMWorkflowController
    and instead talk to
    AMWorkflow
    directly. It has a method
    +runWorkflowAtURL:withInput:error:
    that lets you run a workflow without using
    AMWorkflowController
    .
  • If you need more control you could create a separate tool to run this workflow, and then invoke that tool from your automator action. This tool could use

    AMWorkflowController
    because it could guarantee that it uses it on the main thread.
  • You could use Objective-C for your automator action. Objective-C gives you more control over the thread on which your code runs, so you could then bounce to the main thread for your

    AMWorkflowController
    work.

Please note that these are just suggestions. I haven’t prototyped any of them, so I can’t guarantee that they’ll actually work )-: Also, there may be other alternatives that I’ve not considered; Automator isn’t something I support day-to-day.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replacing the line:


run_(me)


with the line:


my performSelectorOnMainThread:run_(pWorkflow) withObject:me waitUntilDone:true


still results in the following error message:


"AMWorkflowController running should only be done on the main thread!"


Am I calling "performSelectorOnMainThread" improperly or could there be a logic error in the code that generates the error message?

Honestly I don’t know how ASOC interacts with

-performSelectorOnMainThread:***
. However, my general experience with AppleScript is that it’s not safe to interact with the same script instance from multiple threads, so I very much doubt this approach is going to work.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"