Re: Let the runloop process its queue during a long operation
Re: Let the runloop process its queue during a long operation
- Subject: Re: Let the runloop process its queue during a long operation
- From: Andreas Grosam <email@hidden>
- Date: Thu, 7 Oct 2010 13:58:00 +0200
On Oct 7, 2010, at 9:48 AM, eveningnick eveningnick wrote:
> Actually, by "processing" i mean a lot of AppleScript calls, some of
> which return NSAppleEventDescriptors.
> I am not sure how it is happening under the hood (if someone could
> explain me...), but what i see is: i call
> NSAppleEventDescriptor *resultFromScript = [myapplescript
> executeAndReturnError];
> and then this call returns _only after_ the result is available (i.e.,
> the "return" operator in applescript has been called).
AppleScript. This raises the question whether AppleScript is thread safe and/or can be executed on secondary threads.
Most sources indicate and the most recent official document about thread safety
<http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html#//apple_ref/doc/uid/10000057i-CH12-SW1>
state that it is not thread safe and must be executed on the main thread only.
However, the official AppleScript release notes <http://developer.apple.com/library/mac/#releasenotes/AppleScript/RN-AppleScript/RN-10_6/RN-10_6.html#//apple_ref/doc/uid/TP40000982-CH106-SW3> mention this:
Thread Safety
OSA and AppleScript are now thread-safe: they may be safely called on a non-main thread or from multiple threads without any locking in the client code. This also applies to NSAppleScript. This does not mean that AppleScript is totally concurrent: AppleScript uses locking to ensure that any single connection (a ComponentInstance) will only run on one thread at a time. Because of the size of the locking granularity, trying to manipulate the same script from multiple threads at once may still be subject to race conditions, and is not recommended.
Before using a scripting component on a background thread, developers should test the component’s “thread-safe” bit (cmpThreadSafe in theComponentDescription’s componentFlags.) Test the generic component before using OSA on a background thread, and then test the specific language component before using it on a background thread.
Scripting Additions and Thread Safety
Since a scripting addition can contain arbitrary code, a given addition command may or may not be thread-safe: offset of is, for example, butdisplay dialog is not. For compatibility, addition commands are presumed to be thread-unsafe, and will be executed on the main thread. Commands may be marked as thread-safe using an expanded Info.plist definition; see TN1164, Scripting Additions for Mac OS X, for details. Coercion handlers in scripting additions must be thread-safe; again, see TN1164 for details. Scripting addition developers should review and, if necessary, update their additions for thread-safety.
> Does my application register some "event listeners", that wait for
> AppleScripting server application (it is Microsoft Word) to post this
> event?
> Does that mean i will need the run loop?
When using AppleScript - I suspect you will need a runloop. But - please correct me if I'm wrong - I‘m pretty sure there is already a runloop for secondary threads when using a NSOperation which is scheduled through a NSOperationQueue. You can test whether a thread has a runloop:
NSRunLoop* currentRunloop = [NSRunLoop currentRunLoop];
> Maybe it's better and easier
> to create the thread manually instead of using NSOperation?
No, I don't think so. An NSOperation and NSOperationQueue is quite convenient.
A custom NSOperation requires to override the main method only - and possibly init and dealloc methods.
As an additional feature, your custom operation may know for itself whether it can run in the background. This depends on the code it executes and what scripts it may run. So you can conditionally execute them in either a secondary thread or as an alternative in the main thread:
if ([myOperation canRunInBackground])
[self.operationQueue addOperation:myOperation];
else
[[NSOperationQueue mainQueue] addOperation:myOperation]; // this blocks the main thread for undetermined duration
You create the operation queue which schedules operations on a secondary thread simply by invoking alloc and init.
How about making a custom NSOperation, overriding the methods -main (really only this method, and possibly init and dealloc) then testing whether it runs in a background thread? :)
best
> Thank you
>
>> It will be much easier to use a custom subclass of NSOperation for this kind of problem.
>> The operation's -main method should perform the transformation in a peace-wise manner and thereby repeatedly checking its cancelation state (-isCancelled method), like:
>>
>> - (void) main {
>> // runs on a secondary thread
>> NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
>> ...
>> while (![self isCancelled] && !done) {
>> // transform a peace of data
>> ...
>> }
>>
>> [delegate fileTransformOperationDidFinish:self];
>>
>> [pool release];
>> }
>>
>> You add the operation to a NSOperationQueue instance which schedules its operations onto a secondary thread. From your main thread you may then cancel the operation by sending it the -cancel message.
>>
>> There are several ways to notify the application (or some object) when the task is finished. Using a delegate is safe and easy. You may consider to define a protocol for the delegate. The delegate method may also schedule its actual work to the main thread (via -performSelectorOnMainThread:withObject:waitUntilDone:) if this is necessary.
>>
>> Just be careful when your task requires itself a runloop (e.g. using asynchronous NSURLConnection) - since there exists no (implicit) one when invoking an NSOperation's -main method on a secondary thread. Properly implementing this will require more elaborated code, though.
>>
-------------------------------
Andreas Grosam
Eisenbahnstr. 27
D-79650 Schopfheim
phone: +49 7622 1741
phone/Fax: +49 7622 697 639 0
email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden