unresponsive cancel button

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?

Thanks, Rob

Archive the Folder for the project and then post it. I might be able to help.

Thanks,

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.

Cheers, Rob

Get rid of the “delay 1” – use a timer. See if that helps.

Yeah - I did change it over to NSTimer and its brilliant. A whole new world.

Rob

I’ve tried to figure out how to use NSTimer for my own cancel button problem but am at a loss. Please post the code.

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.

Rob

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.

Rob