Hi All,
This is the age old problem of unresponsive Ui when script is running.
I have almost finished converting my big app over to ASOC. It really works great with about 40% less code, thanks to bindings. Basically it is a wrapper for rsync and launches rsync in background and updates the progress in a progress window with progress bar and two text fields to show transfer info.
In the old ASS version the cancel button worked well most of the time, occasionally freezing only during a very long rsync session. Now in ASOC, the cancel button and Progress window is completely unresponsive. Nothing, Nada…
Using Command-period does however cause the session to end and do finish up.
When user presses the “backup” button, it launches rysnc in background and checks the process pid in a loop that repeats with “delay 1” to give it a fair speed of updating the progress. In the loop the rsync output is parsed for progress % and file information.
I have tried removing the parsing part of the loop and just keep the “delay 1” which makes no difference. This is the same code as in the ASS app, except for the way it sets the value of progress bar and text fields.
The delay loop essentially:
repeat while bool_is_process_running
--parse rsync output here and update progress bar and text fields
delay 1
if not bool_is_process_running then exit repeat
end repeat
Any ideas why this same progress window set up in ASOC is 100% frozen? Anyone seeing similar UI issues?
I sorted all this out by using NStimer instead of ‘delay’, which was always problematic in ASS apps when used as a loop to pause the flow. There is a problem ( bug ) with using delay now anyways in that it causes a huge CPU spike when invoked. Now with NSTimer, the UI is totally responsive.
I think I already posted this somewhere and it may not apply to your case but previously I had something like this:
set pid to do shell script "rsync options paths output"
repeat while count of paragraphs of (do shell script ("ps " & pid)) > 1 --as long as rsync is running
delay 1
end repeat
--continue with script
This binds up the UI and makes the cancel button very unresponsive. The delay command is the culprit and now it is broken, running cpu up to 100%.
property rsyncTimer: missing value
set pid to do shell script "rsync options paths output"
set rsyncTimer to NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(1, me, "loopCheck:", missing value, true)
on loopCheck_(sender)
if count of paragraphs of (do shell script ("ps " & pid) > 1 then
--process rsync stats
else
rsyncTimer's invalidate() -- here is how you quit the loop
my finishUp() -- continue with script if wanted
end loopCheck_
Now the UI is completely responsive and the cancel button works! In my case the cancel button kills the rsync process.
Hope that helps and/or let me know what you want to happen.
Thanks Rob. It’s still somewhat confusing. It wouldn’t work until I forced the “Cancel” button on the sheet to be “enabled” after I started the timer, even though it was enabled to begin with.
property NSTimer : class "NSTimer" of current application
property theTimer : missing value
on showPanelWindow_(sender) -- triggered by button in main window
tell class "NSApplication" of current application
its sharedApplication's beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo_(panelWindow, mainWindow, me, "didEndSheet:", missing value)
set theTimer to NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(1, me, "loopCheck:", missing value, true)
its cancelStatusButton's setEnabled_(true)
end tell
end showPanelWindow_
on loopCheck_(sender)
if ((my panelWindow's isVisible()) is equal to true) then
else
theTimer's invalidate()
-- continue with script if wanted
end if
end loopCheck_
Did you use Shane’s example for sheets that uses the sheet protocol? It seems something is funky with the sheet if the cancel button isn’t working.
My call for the sheet is:
on showCustomSheet_(sender) -- triggered by button in window
set my contextInfo to "Custom"
set theApp to current application's class "NSApplication"'s sharedApplication()
tell theApp to beginSheet_modalForWindow_modalDelegate_didEndSelector_contextInfo_(progresso, mainWindow, me, "sheetDidEnd:returnCode:contextInfo:", missing value)
end showCustomSheet_
The didEndSelector is sheetDidEnd:returnCode:contextInfo: and the superclass overrides this so it works. Shane has the “sheet example” posted on his website.