• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: NSThread question - DO to make it sing
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: NSThread question - DO to make it sing


  • Subject: Re: NSThread question - DO to make it sing
  • From: Candide Kemmler <email@hidden>
  • Date: Wed, 11 Jul 2001 17:47:49 +0200

Le mardi 10 juillet 2001, ` 06:54, Miguel Morales a icrit :
>
> However, this would spawn a thread, but the main thread would wait for
> the secondary thread to finish before continuing, and not give you any
> of the functionality you want of the main thread plugging along. This
> is where DO comes in. I will assume that there is a main object that
> is running in a run loop, and that when the button gets pushed the
> method -(void)button:(NSData *)data is called, and that there is
> another method in the object that draws to the screen (also in the main
> object) called -(oneway void)display:(bycopy NSData *)data.

Great ! I've read the chapter on DO in "Object-Oriented Programming and
the Objective-C Language" and I'm enthusiast about learning more on DO
in OC. For a java-fan like me, it's like doing RMI and multi-threading
at once ! However I find it a little odd to be forced to do rmi (or rpc,
or whatever-you-name-it) just to do multi-threading.

You said that the code snippet you give "would spawn a thread, but the
main thread would wait for the secondary thread to finish before
continuing" !!!!! That's the whole point of doing threads !

Consider the following bit of java code:

public void actionPerformed ( ActionEvent evt ) {
if ( evt.getSource () == myButton ) {
( new Thread () {
public void run () {
renderMyImage ();
}
} ).start ();
}
}

Isn't there a way as simple as this do achieve the same effect in
Objective-C/Cocoa ?

Anyway I've tried to go your way, but I wasn't lucky:

I wrote a MapRenderer class like this:

@implementation MapRenderer

- (oneway void) renderImage: (bycopy NSData *) data
{
id mainProxy;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init ];
NSSize aSize;
NSImage *cachedImage;

aSize = NSMakeSize (450, 345 );

mainProxy = [ NSConnection
rootProxyForConnectionWithRegisteredName:@"mainThread" host:@"" ];
cachedImage = [[NSImage alloc] initWithSize:NSMakeSize(aSize.width,
aSize.height)];
[ cachedImage lockFocus ];
[ [ NSColor blueColor ] set ];
[[ NSBezierPath bezierPathWithRect:NSMakeRect ( 0, 0, aSize.width,
aSize.height )] fill ];
[ cachedImage unlockFocus ];

[ mainProxy setImage: cachedImage ];

[ pool release ];
}

in my MapController class, I have a masterConnection defined in init
like you said and also a mapRenderer allocated and initialized.
Naturally I also have a setImage: (NSImage *) anImage method

When my button's triggered, I do:

[ NSThread detachNewThreadSelector:@selector(renderImage)
toTarget:mapRenderer withObject:data ];

The result is a catastrophy of errors and exceptions:

_NSAutoreleaseNoPool ():...
-[MapRenderer renderImage]: selector not recognized

just leaking, just leaking,...
selector not recognized..., InvalidArgumentException...

What's wrong ???

And a big thank you for your long explanations ! :-)


Regards,

Candide

PS: I don't get the following: "I will assume that there is a main
object that is running in a run loop". Isn't that my application ?

> in the main object (main thread)
> ---------------
> //In some initialization routine (-init?)
> masterConnection = [NSConnection defaultConnection]; //Gets the default
> connection for this thread
> [masterConnection setRootObject:self];
> [masterConnection registerName:@"mainThread"]; //registers itself
> on the network so it can take input
> .........
>
> -(void)button:(NSData *)data
> {
> [NSThread detachNewThreadSelector:@selector(setData)
> toTarget: myView withObject: data];
> }
>
> in the myView object (will be in a new thread most of the time)
> ---------------
> -(oneway void) setData:(bycopy NSData *) data
> {
> id mainProxy; //A proxy object for the main object in the
> main thread (how we call back when done)
>
> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc ] init];
>
> mainProxy = [NSConnection
> rootProxyForConnectionWithRegisteredName:@"mainThread" host:@""];
> //picks up the network connection mainThread, and makes a
> proxy object so we can call home
>
> myData = data; //Already a copy from the bycopy keyword
> [self doImage]; //do processing, but DO NOT write to the screen
>
> [mainProxy display: myData];
> //Calls back to the main thread, giving it the updated
> information, and telling it to draw it to
> //the screen (so only the main thread draws to the screen)
>
> [pool release];
> //Clean up afterwards, thread should automatically die
> because we have no run loop for this thread
> }
>
> Note the oneway and bycopy keywords. oneway tells the DO system that
> setData can be run independently of the main thread, otherwise the main
> thread will wait for the sub thread to do it's processing (not what you
> want). bycopy tells DO to send a copy of the data object, not a
> proxy. This can greatly reduce the overhead of sending messages in
> some situations.
>
> Now the caveats: I just typed this in, and DO can be confusing, so
> this is probably not bug free (some of the DO mavens out there can
> point out my mistakes :-) The DO is hard to learn at first. Look at
> Object-Orient Programming and the Objective-C Language, and some of the
> DO examples. But once you get DO it is very cool. With a couple of
> very minor changes the above code can be changed so that the secondary
> thread persists and can process data whenever you want (just have the
> thread vend a connection and send the thread into a run loop), or the
> data can be processed by a process on another machine (some people
> prefer to set up ports instead of registering a name when just doing
> thread to thread communication, but I do distributed processing, and
> like the elegance of the same interface whether the communication is
> local or remote) So DO is definitely worth the time, and have fun.
>
> Hope this helps,
>
> -Miguel F. Morales
>
>
>
>
>> Candide wrote:
>>
>>
>> I still have an error (signal 10 (SIGBUS)). I'll explain exactly what I
>> do:
>>
>> I have a -(void)doImage; method in a custom NSView object. This is the
>> method I'm calling in the new Thread, and it goes like this:
>>
>> -(void)doImage
>> {
>> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc ] init];
>> [ self display ];
>> }
>>
>> the method in which I call it goes like this:
>>
>> -(void) setData:(NSData *) data
>> {
>> myData = [[NSData alloc] initWithData:data];
>> cachedImage = nil;
>> [NSThread detachNewThreadSelector:@selector(doImage) toTarget:self
>> withObject:nil];
>> }
>>
>> Still obscure to me what causes the crash...
>>
>>> Le mardi 10 juillet 2001, ` 11:59, Stefan Jung a icrit :
>>>
>>> Am Dienstag, 10. Juli 2001 um 10:47 schrieb Candide Kemmler:
>>>
>>>> Hi,
>>>>
>>>> I have a button (several of them actually) which triggers a long
>>>> rendering. My application not being multithreaded, the button stays
>>>> blue for a long while, until the rendering's finished. I tried to do:
>>>>
>>>> [ NSThread detachNewThreadSelector:@selector(display) toTarget:self
>>>> withObject:nil ];
>>>>
>>>> But then I get
>>>>
>>>> Jul 10 10:46:50 TT[979] *** _NSAutoreleaseNoPool(): Object 0x145d390
>>>> of class NSBezierPath autoreleased with no pool in place - just
>>>> leaking
>>>> Jul 10 10:46:50 TT[979] *** _NSAutoreleaseNoPool(): Object 0x145d3f0
>>>> of class NSBezierPath autoreleased with no pool in place - just
>>>> leaking
>>>> Jul 10 10:46:50 TT[979] *** _NSAutoreleaseNoPool(): Object 0x145d300
>>>> of class NSCalibratedRGBColor autoreleased with no pool in place -
>>>> just leaking
>>>>
>>>> What's wrong with my call ?
>>> Your call is Ok, but you have to set up your own NSAutoreleasePool.
>>> For
>>> your primary thread this is done by your application object, for
>>> Threads you have to do it on your own.
>>>
>>> NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
>>> The *pool destroys itself at the next opportunity, but releases all
>>> autoreleased objects before. so there is no [pool release].
>>>
>>> Stefan


  • Follow-Ups:
    • Re: NSThread question - DO to make it sing
      • From: "Dennis C. De Mars" <email@hidden>
References: 
 >Re: NSThread question - DO to make it sing (From: Miguel Morales <email@hidden>)

  • Prev by Date: Continuous controls: detecting when the last message comes through
  • Next by Date: Re: Continuous controls: detecting when the last message comes through
  • Previous by thread: Re: NSThread question - DO to make it sing
  • Next by thread: Re: NSThread question - DO to make it sing
  • Index(es):
    • Date
    • Thread