Re: NSTextView won't update via NSThread
Re: NSTextView won't update via NSThread
- Subject: Re: NSTextView won't update via NSThread
- From: "Stephen J. Butler" <email@hidden>
- Date: Fri, 6 Nov 2009 16:08:07 -0600
On Fri, Nov 6, 2009 at 3:50 PM, Dalton Hamilton <email@hidden> wrote:
> Well, I would think Cocoa would let me manage whether I'm calling it
> multiple times and just do what I'm asking.
Multithreading, as a general problem, is HARD. To do what you're
suggesting ("just do what I'm asking") the framework would have to
lock all of these things:
- NSTextView instance
- NSTextStorage instance
- NSMutableString instance
How is it supposed to do that? Use one big lock, and your program
spends most of its time waiting for the lock. Use smaller locks, and
you run the very real risk of introducing deadlocks.
> So, I now I'm trying to set an NSLock, then call the worker Thread and put
> the output into a MutableString. The Thread then UnLocks the NSLock which
> tells the Main Thread the NSMutableString has data. The main thread calls
> [NSTextView setString: myMutableString]; and this continues looping through
> the work items. When all items are done, the NSTextView updates all at once
> -- nothing displays in the NSTextView until the thread is finished running
> even though my main program/thread is continually blocking on the LOCK,
> obtaining the LOCK (when the thread releases it) then updating NSTextView,
> UNLOCKING, and looping. In general that's what I'm doing. It just isn't
> working.
Well, from the code you've shown us, you call "[outHandle
readDataToEndOfFile]". Which means it waits for all the data before
updating the view. So yes, the view will be empty until the tool is
complete because that's what you told it to do.
If you want to update as the tool outputs stuff, you need to
readInBackgroundAndNotify and run the runloop. You can do all this
without threads...
> Surely this can't be this complicated. I've done lots of Cocoa programming
> -- self taught -- and have never ran across this problem before.
>
> Thank you all for helping me understand this. I did read the page(s) the
> link refers to above but I can't devise an action/solution from what it is
> telling me. It just explains how it works. I'm sure it is there and I just
> don't understand.
... but if you still want to use threads, here's the simple way to do it:
[NSThread detachNewThreadSelector:@selector(runTask:) toTarget:self
withObject:nil];
- (void)runTask:(id)sender
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSTask *task = [[NSTask alloc] init];
NSPipe *inPipe = [NSPipe pipe], *outPipe = [NSPipe pipe];
NSFileHandle *outHandle = [outPipe fileHandleForReading];
NSData *outData;
NSString *outString;
NSMutableArray *arguments = [NSMutableArray arrayWithObjects: @"-l", nil];
[arguments addObject:@"/Applications"];
[task setLaunchPath:@"/bin/ls"];
[task setArguments: arguments];
[task setStandardOutput:outPipe];
[task setStandardError:outPipe];
[task setStandardInput:inPipe];
[task launch];
outData = [outHandle readDataToEndOfFile];
[task waitUntilExit];
[task release];
outString = [[[NSString alloc] initWithData:outData
encoding:NSUTF8StringEncoding] autorelease];
[self performSelectorOnMainThread:@selector(updateOutput:)
withObject:outString waitUntilDone:NO];
[pool release];
}
- (void)updateOutput:(NSString*)outString
{
[[[myTextView textStorage] mutableString] appendString:outString];
}
_______________________________________________
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