Re: Services and threads... Help!
Re: Services and threads... Help!
- Subject: Re: Services and threads... Help!
- From: Mark Munz <email@hidden>
- Date: Mon, 24 Jan 2005 15:52:37 -0600
Check out the sample service at:
/Developer/Examples/AppKit/SimpleService
When you specify the NSServices Array in your Info.plist, you give it the method name to call for the service menu item.
- (void)MyMethod:(NSPasteboard *)pboard userData:(NSString *)data error:(NSString **)error
{
// pasteboard needs to be set before you leave here
}
This would not be good if you're trying to create a commercial app, but you can get away with putting up some UI in a modal fashion. You normally do not want to start creating modal dialogs -- but if you're solving a custom problem, it may be acceptable to your customer.
In your method, do whatever is needed, bring up the UI, etc, and then put the data on the given pasteboard before exiting the call. The pasteboard is a temporary one and is not guaranteed to be around after you leave the method.
I have also seen the approach of TWO services, one sets up the UI and waits for the user to interact with the UI (just keep the pasteboard -- and remember to retain it). The second call replaces the selection with the updated results. I believe Nisus Thesaurus does this (Look up Selection ; Replace Selection).
Mark Munz
On Jan 24, 2005, at 5:21 AM, Ken Tabb wrote:
Hi folks,
I have an app offering a service putting text on the pasteboard. If I just get it to put one piece of text on the pasteboard (eg. @"hello") it works fine. However my particular service needs some input from the user before it can put the correct text on the pasteboard. So for instance, on the keypress (or Service menu invocation), the service offers up a GUI and lets the user select which text to put on the pasteboard. At this point things don't work quite how I'd like... nothing actually gets pasted in to the calling app.
The service works fine, the GUI works fine, and the correct stuff gets put on the pasteboard fine. The reason it doesn't work is because the calling app (TextEdit, for example) uses the pasteboard it supplied before I've put anything into it, hence nothing appears to have been pasted, whereas in fact "" (empty string) was indeed pasted. Subsequent attempts to put stuff into this pasteboard fall flat, as TextEdit is no longer using the pasteboard, even though my stuff is now in the pasteboard.
The problem I face is that, with Services, there seems to be the assumption that by the time your service method (the one that gets invoked and supplied a pasteboard) has ended, your pasteboard will be ready for the calling app (TextEdit) to use. And that isn't the case with me... my method fires up a GUI, and I have to wait for the user to decide what they want before I'm ready to paste.
So I'm guessing that what I need to do is prevent my service method from finishing, until I'm ready to paste? This way TextEdit has to hold on until I'm ready; granted there is a default timeout for services of 30 secs (which can be extended) but 30 secs should be loads of time for my users... and if not I can work on that aspect later once the thing works at all 8^)
I've found that if my service method simply sleeps the current thread (the app is single threaded so far by the way) for <30 secs (the default timeout for services) and then adds @"hello" to the pasteboard before ending, everything works well and I get "hello" appear in TextEdit. This is fine except to say my app is hung for that <30 secs of course (GUI and everything). Thus although this proves the calling app (TextEdit) is prepared to wait, it's not a solution as the user can't use the GUI to make their decision. Zut alors.
I'm loathed to try to run the event loop in a second thread (as in "not in the main thread") as I have a feeling my window events (in thread 2) will then be separated from my app events (in thread 1) which will confuse the bejesus out of me.
So I think what I'd like to do is run my service method in thread 2, with the app's processing and events and GUI in thread 1. That way the service method can keep sleep for a second at a time until such time as the main thread (with the GUI) has made a decision, whereupon thread 2 can put the right stuff in the pasteboard, and end the method (allowing TextEdit back at the reigns).
What I suppose I'm asking is if either of these are possible:
[1] Is there any way to fire a service method into another thread? I know how to fire one method from another into a second thread within Cocoa, but I don't know how to say to the Services system "when you fire this method, please do it in a different thread"
[2] If I make a "SystemListener" class (which tells the app delegate to fire up the GUI etc.), which in it's -init spawns a second thread, in which it sets itself as the service provider using [NSApp setServicesProvider:self] (so that this object is the thing that receives service requests), will service requests be coming in to the object on thread 2 (in which the "setServicesProvider" was called) or in the main thread?
I'm familiar with multi-threaded programming, just not with Services 8^(
Failing this I might have to start using NSAppleScript... cripes it shouldn't have to come to this should it?!
Any nuggets of help would be much appreciated, thanks in advance,
Ken
p.s. if only services had some sort of "OK the pasteboard's ready for you to use now" API...
- - - - - - - - - -
Dr. Ken Tabb
Mac & UNIX Developer - Health & Human Sciences
Machine Vision & Neural Network researcher - School of Computer Science
University of Hertfordshire, UK
http://www.health.herts.ac.uk/ken/
Certified non-Microsoft Solution Provider
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden