• 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
NSThread question - DO to make it sing
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

NSThread question - DO to make it sing


  • Subject: NSThread question - DO to make it sing
  • From: Candide Kemmler <email@hidden>
  • Date: Thu, 12 Jul 2001 11:35:51 +0200

Dibut du message riexpidii :

> De : Candide Kemmler <email@hidden>
> Date : Jeu 12 jul 2001 11:20:31 Europe/Paris
> @ : "Dennis C. De Mars" <email@hidden>
> Cc : email@hidden
> Objet : Rip : NSThread question - DO to make it sing
>
> Le jeudi 12 juillet 2001, ` 09:58, Dennis C. De Mars a icrit :
>
>> on 7/11/01 10:39 AM, Candide Kemmler at email@hidden wrote:
>>
>>>
>>> Le mercredi 11 juillet 2001, ` 06:57, Dennis C. De Mars a icrit :
>>>
>>>> on 7/11/01 8:47 AM, Candide Kemmler at email@hidden wrote:
>>>>
>>>>> 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 ?
>>>>
>>>> If your "renderMyImage" routine used any Swing classes to do its
>>>> rendering,
>>>> you'd have a problem with this code too, because Swing is not
>>>> thread-safe
>>>> either; you are supposed to do all drawing in the main thread there
>>>> too.
>>>>
>>>> I think this is true of pretty much any GUI system of any complexity
>>>> ever
>>>> devised -- you simply have to defer drawing to the main thread.
>>>>
>>>> - Dennis D.
>>>
>>> consider the following renderMyImage implementation (not tested):
>>>
>>> java.awt.Image renderMyImage () {
>>> java.awt.image.BufferedImage image = new
>>> java.awt.image.BufferedImage ( 450, 345,
>>> BufferedImage.TYPE_INT_ARGB );
>>> Graphics2D g2d = image.createGraphics ();
>>> g2d.setColor ( Color.red );
>>> g2d.fillRect ( 0, 0, 450, 345 );
>>> return image;
>>> }
>>>
>>> There's no Swing code involved, and now I have an image I can send
>>> to a
>>> Swing component to draw it with something like
>>>
>>> g.drawImage ( image, 0, 0, this );
>>>
>>> Simple enough, huh ? And that's exactly what I'd like to do in
>>> OC/Cocoa.
>>
>> Well, if you are talking about rendering an image offscreen in a
>> secondary
>> thread, but only displaying it onscreen in the main thread, I think you
>> should be able to do that safely in Cocoa...if you look at:
>>
>> http://developer.apple.com/techpubs/macosx/ReleaseNotes/ThreadSupport.html
>>
>> ...they have a discussion of modifying NSViews in threads. Although I
>> could
>> have used a more thorough discussion than Apple provides in this
>> release
>> note, they seem to imply that the only thing to really avoid is doing
>> actual
>> on-screen updates anywhere but in the main thread, which is
>> understandable
>> since otherwise the main thread and another thread could be trying to
>> modify
>> the same on-screen pixels at the same time. But, if you have a thread
>> drawing to an off-screen image that is owned by that thread, that
>> should
>> work. At least that's the impression I get, I haven't done too much of
>> this
>> myself.
>>
>> The original code you posted is doing its work offscreen, so I think it
>> should be all right. Some of the errors you were getting might be due
>> to the
>> fact that the line:
>>
>> [ NSThread detachNewThreadSelector:@selector(renderImage)
>> toTarget:mapRenderer withObject:data ];
>>
>> should have been
>>
>> [ NSThread detachNewThreadSelector:@selector(renderImage:)
>> toTarget:mapRenderer withObject:data ];
>>
>> The colon is part of the selector name, so I think that's why you got
>> several messages about an unrecognized selector.
>
> Right, I didn't get that. It works now... most of it: it seems that the
> image is rightly created and rendered, but nothing appears on-screen.
> This is the whole chain of calls:
>
> in MapController, when the button's triggered:
>
> [ NSThread detachNewThreadSelector:@selector(renderImage:)
> toTarget:mapRenderer withObject:data ];
>
> in MapRenderer, this is the renderImage method:
>
> - (oneway void) renderImage: (bycopy NSData *) data
> {
> id mainProxy;
> NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
> NSSize aSize;
> NSImage *cachedImage;
>
> NSLog ( @"in renderImage code" );
> aSize = NSMakeSize ( 550, 445 );
>
> cachedImage = [[NSImage alloc] initWithSize:aSize];
>
> [cachedImage setBackgroundColor:[[NSColor redColor]];
>
> [cachedImage lockFocus];
> [[NSColor blackColor] set];
> [NSBezierPath fillrect:NSMakeRect(0,0,aSize.width,aSize.height)];
> [cachedImage unlockFocus];
>
> [mainProxy setImage:cachedImage];
>
> [pool release];
> }
>
> back in MapController, the Image is set (MapController is the
> "mainThread" DO):
>
> - (void) setImage:(NSImage *) anImage
> {
> NSLog ( @"setImage is invoked, its size is %f, %f", [anImage
> size].width, [anImage size].height );
> [mapView setImage:anImage ];
> }
>
> in MapView, setImage is defined like so:
>
> - (void) setImage:(NSImage *) anImage
> {
> NSLog (@"set cachedImage in MapView" );
> cachedImage = image;
> NSLog ( @"setImage is invoked, its size is %f, %f", [cachedImage
> size].width, [cachedImage size].height );
> [self display];
> }
>
> Now, drawRect:
>
> - (void) drawRect: (NSRect) frame
> {
> float cx = [self bounds].size.width/2;
> float cy = [self bounds].size.height/2;
> NSLog ( @"drawRect is invoked, cachedImage's size is %f, %f",
> [cachedImage size].width, [cachedImage size].height );
> cx -= [cachedImage size].width/2;
> cy -= [cachedImage size].height/2;
> [cachedImage compositeToPoint:NSMakePoint(cx,cy)
> operation:NSCompositeSourceOver];
> }
>
> The size of the image is rightly logged every time, yet nothing appears
> on-screen (neither a black nor a red rectangle). Everything seems
> all-right to me though. Any Idea ? Oh, And my app just crashes with a
> signal 10 (SIGBUS) when I try to resize its window...
>
> Thanks for your help.
>
> Candide
>
>> - Dennis D.
>> _______________________________________________
>> cocoa-dev mailing list
>> email@hidden
>> http://www.lists.apple.com/mailman/listinfo/cocoa-dev


  • Prev by Date: NSProgressIndicator disabled on sheet
  • Next by Date: Re: NSThread question - DO to make it sing
  • 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