[SOLVED] NSProgressIndicator, runModalForWindow, detachNewThreadSelector -> Not good...
[SOLVED] NSProgressIndicator, runModalForWindow, detachNewThreadSelector -> Not good...
- Subject: [SOLVED] NSProgressIndicator, runModalForWindow, detachNewThreadSelector -> Not good...
- From: Dix Lorenz <email@hidden>
- Date: Thu, 20 Apr 2006 15:17:05 +0200
Just for the record, turns out I had to explicitly close the
controller before releasing it:
void mM4Dialog_RunProgressTask(DLProgressTask *inTask)
{
Dialog_ProgressTask *theController = [[Dialog_ProgressTask alloc]
initWithTask:inTask];
NSTimer *theTimer = [[NSTimer
timerWithTimeInterval:(NSTimeInterval)0.2
target:theController
selector:@selector(updateStatus:)
userInfo:nil
repeats:YES] retain];
[[NSRunLoop currentRunLoop] addTimer:theTimer
forMode:NSModalPanelRunLoopMode];
[NSThread detachNewThreadSelector:@selector(execute:)
toTarget:theController withObject:NULL];
int theResult = [NSApp runModalForWindow:[theController window]];
[theTimer invalidate];
[theTimer release];
[theController close]; // <<< New code
[theController release];
}
Why I have to do that or why it was not necessary when I didn't
update the NSProgressIndicator, I don't know. I didn't find anything
in the docs to suggest this...
Dix
On 04.04.2006, at 10:42, Dix Lorenz wrote:
Hi,
I have a problem showing a very simple Window with a progress bar,
it has me stumped. This is my WindowController:
@interface Dialog_ProgressTask : NSWindowController
{
IBOutlet NSProgressIndicator *mProgressIndicator;
IBOutlet NSTextField *mStatusField;
IBOutlet NSButton *mCancelButton;
DLProgressTask *mTask;
}
- (id)initWithTask:(DLProgressTask *)inTask;
- (void)execute:(id)inArgument;
- (void)updateStatus:(NSTimer*)inTimer;
@implementation Dialog_ProgressTask
- (id)initWithTask:(DLProgressTask *)inTask
{
if ((self = [super initWithWindowNibName:@"Dialog_ProgressTask"])) {
mTask = inTask;
}
return self;
}
- (void)execute:(id)inArgument
{
mTask->Execute();
}
- (void)updateStatus:(NSTimer*)inTimer
{
#pragma unused (inTimer)
if (!mTask)
return;
if (mTask->isFinished()) {
mTask = NULL;
[NSApp abortModal];
return;
}
DLDouble theValue = mTask->CompletedPart();
[mProgressIndicator setDoubleValue:theValue];
}
@end
This is the calling function:
void mM4Dialog_RunProgressTask(DLProgressTask *inTask)
{
Dialog_ProgressTask *theController = [[Dialog_ProgressTask alloc]
initWithTask:inTask];
NSTimer *theTimer = [[NSTimer
timerWithTimeInterval:(NSTimeInterval)0.2
target:theController
selector:@selector(updateStatus:)
userInfo:nil
repeats:YES] retain];
[[NSRunLoop currentRunLoop] addTimer:theTimer
forMode:NSModalPanelRunLoopMode];
[NSThread detachNewThreadSelector:@selector(execute:)
toTarget:theController withObject:NULL];
int theResult = [NSApp runModalForWindow:[theController window]];
[theTimer invalidate];
[theTimer release];
[theController release];
}
I am pretty sure retain/release for the NSTimer are not necessary,
but AFAIK they don't hurt either and removing it doesn't change
anything anyway. mTask->Execute() is pure C++, does not call any
Cocoa and is thread-safe. When the Task is finished, [NSApp
abortModal] gets called as it should be, the program is usable
again, the results show up, everything is great... Except that the
window with the ProgressIndicator is still there. After a while
(sometimes very soon, sometimes it takes a few seconds) the program
crashes:
#0 0x909c0120 in objc_msgSend
#1 0x928e2c20 in __NSFireMainThreadPerform
#2 0x9078ef2c in __CFRunLoopPerformPerform
#3 0x9075ea68 in __CFRunLoopDoSources0
#4 0x9075df98 in __CFRunLoopRun
#5 0x9075da18 in CFRunLoopRunSpecific
#6 0x9317d1e0 in RunCurrentEventLoopInMode
#7 0x9317c874 in ReceiveNextEventCommon
#8 0x9317c6e0 in BlockUntilNextEventMatchingListInMode
#9 0x9367b104 in _DPSNextEvent
#10 0x9367adc8 in -[NSApplication
nextEventMatchingMask:untilDate:inMode:dequeue:]
#11 0x9367730c in -[NSApplication run]
#12 0x93767e68 in NSApplicationMain
#13 0x00005420 in main at main.m:13
What I really don't understand: if I remove the line
[mProgressIndicator setDoubleValue:theValue];
the whole thing works perfectly: The window is destroyed as soon as
it finishes and AFAICT the program is stable, I can call that
routine again and again, no problems. Of course the
progessindicator isn't updated, so it's not really a solution.
Also if I do not use detachNewThreadSelector to execute the task
but just call it from updateStatus the crash occurs if I also
update the ProgressIndicator.
Normally I would say the problem has to be in mTask->Execute(), but
I really doubt it. It is complicated code, no question, but so far
it has been very stable for me and the problem really only occurs
when mProgressIndicator is updated in any way (using it
indeterminate or using threaded animation doesn't change anything).
Somebody please tell I've done something very stupid in my code
which I just can't see...
Thanks,
Dix
_______________________________________________
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