RE: Threading - How its done?
RE: Threading - How its done?
- Subject: RE: Threading - How its done?
- From: Karl von Moller <email@hidden>
- Date: Tue, 6 May 2008 12:17:24 +1000
Hi to all,
I have been working on a simple application that lists all available
PDF's in the Users Documents Folder. I want to fill a Table view with
only PDF's that exist at that location. When the User selects one of
the PDF files (by highlighting it in the Table View) it is
automatically loaded into a PDF View. To make the user interface
appear more responsive and to let the User know what's going on when a
large PDF file is loaded, I thought that using Threads would be my
best answer. I have no experience using threads and like most people
out in the wild, have no clear starting place to begin learning. The
easy answer perhaps is to commit to building for 10.5 and use
NSOperation instead, but I need to be able to build for 10.4 as well!
So I have started down the path of NSThread using this to spawn a new
thread from my main Thread:
[NSThread detachNewThreadSelector:@selector(myMethod:) toTarget:self
withObject:nil];
I have Garbage collection turned ON in my project settings but have
opted to code an Autorelease Pool in myMethod just incase! Here is a
portion of my code:
- (void)awakeFromNib
{
//****** countProcessors will log the number of available CPU cores
available.
int countProcessors = MPProcessorsScheduled();
NSLog(@"the Number of processors on this system are: %d",
countProcessors);
// **** Init the Mutable arrays which will hold the path and file
name values
resultArray = [[NSMutableArray alloc] init];
fileNameArray = [[NSMutableArray alloc] init];
[tableViewOutlet setDelegate:self];
[tableViewOutlet setDataSource:self];
[windowOutlet setTitle:@"PDF Viewer 1.02 beta"];
[resultArray removeAllObjects];
[fileNameArray removeAllObjects];
NSString *myFileName;
NSString *thePath = @"~/Documents/";
NSString *absolutePath = [thePath stringByExpandingTildeInPath];
//** here we setup the default path and open it - read the contents.
If they are PDF's then add them to the array fileNameArray
//resultArray stores just the name of the PDF with out reference to
the rest of the path.
//I have logged the start and end times as well to see whether
Threading makes a big difference and it does!
CFAbsoluteTime elapsedTime, startTime = CFAbsoluteTimeGetCurrent();
NSFileManager *myFileManager = [NSFileManager defaultManager];
NSDirectoryEnumerator *enumerator = [myFileManager
enumeratorAtPath:absolutePath];
while (nil != (myFileName = [enumerator nextObject]))
{
/* don’t enumerate sub directories */
[enumerator skipDescendents];
if ([[myFileName pathExtension] isEqualToString:@"pdf"])
{
[resultArray addObject: [myFileName lastPathComponent]];
[fileNameArray addObject: myFileName];
[tableViewOutlet reloadData];
}
else
{
NSFont *smallBoldFont = [NSFont fontWithName:@"Arial Black" size:9];
[currentFileOutlet setFont: smallBoldFont];
[currentPathOutletLabel setFont: smallBoldFont];
[pathTextOutlet setStringValue: absolutePath];
NSFont *myFont = [NSFont fontWithName:@"Arial Black" size:36];
[numberOfFileOutlet setFont:myFont];
[numberOfFileOutlet setIntValue:[resultArray count]];
}
}
elapsedTime = CFAbsoluteTimeGetCurrent() - startTime;
NSLog(@"list took %f seconds to create. ", elapsedTime);
//******* setup all the text objects with path values etc.
NSString *theFirstIndex = [fileNameArray objectAtIndex:0];
NSString *interFinal = [absolutePath stringByAppendingString: @"/"];
finalStringOutput = [interFinal stringByAppendingString:
theFirstIndex];
[pdfNameTextLabel setStringValue:[theFirstIndex lastPathComponent]];
[currentPathOutlet setStringValue: finalStringOutput];
[fileNameTextOutlet setStringValue: [finalStringOutput
lastPathComponent]];
//*** go to the method openPDFandCreatePreview to open and create an
image preview of the selected PDF. Tried this using threads??
NSLock *myLock = [[NSLock alloc] init];
[myLock lock];
[NSThread detachNewThreadSelector:@selector(openPDFandCreatePreview:)
toTarget:self withObject:nil];
//[self openPDFandCreatePreview:nil]; // this was used without threads
[myLock unlock];
}
Here is the Method that gets called to produce the image preview of
the PDF and to load the PDF into the view. Ideally I would like to
have a progress indicator working as well to give Users some feedback.
The Application is noticeably faster and more responsive with Threads
but will crash after a short while! Why? Every error message reported
after the crash is different so I have no idea what's really going on.
The user interface consists of a spinning progress indicator, a Table
View with 3 columns (icon, File Name and Path), a Text field where the
User can enter a specified Path and two buttons. There are several
text objects to display the chosen file name and path details as well.
I use Notifications to track changes in selection in the Table View.
This Method also calls [NSThread
detachNewThreadSelector:@selector(openPDFandCreatePreview:)
toTarget:self withObject:nil];
-(void)openPDFandCreatePreview:(id)sender
{
//[progressOutlet setUsesThreadedAnimation:YES];
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
[progressOutlet startAnimation:nil];
NSPDFImageRep *pdfRep;
NSImage *pdfImage;
pdfRep = [NSPDFImageRep imageRepWithContentsOfFile: finalStringOutput];
pdfImage = [[[NSImage alloc] init] autorelease];
[pdfImage addRepresentation: pdfRep];
[imageWellOutlet setImage:pdfImage];
PDFDocument *pdfDoc;
pdfDoc = [[[PDFDocument alloc] initWithURL: [NSURL fileURLWithPath:
finalStringOutput]] autorelease];
[pdfOutlet setDocument:pdfDoc];
[progressOutlet stopAnimation:nil];
[pool release];
return;
}
If there is another way to load a PDF into a PDF view using
Multithreading techniques that is easier to understand please let me
know! Any help with this would be much appreciated._______________________________________________
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