我正试图用我正在开发的应用程序来追踪一个冻结问题。我可能在NSAutoreleasePool的深处,正在搞砸事情。
这个应用程序正在播放一个midi文件。如果我注释掉下面使用simRespondToFileNote的“NSAutoreleasePool”代码,它不会冻结。如果我让代码运行,它将在看似随机的点冻结崩溃日志/控制台输出,这似乎并不表明问题发生在何处。
以下是程序流程:
中,并将其路由到主线程,以便我可以进行UI更新和其他一些事情。
下面是执行路由的代码:
- (void)forwardFileNoteIn:(int) note withVelocity: (int) velocity
{
int position = BASS_ChannelGetPosition(midiFileStream, BASS_POS_MIDI_TICK);
float percent = ((float)position / (float)totalTicks);
int ticksInLoop = outLoopTick - inLoopTick;
QWORD bytes=BASS_ChannelGetPosition(midiFileStream, BASS_POS_BYTE); // get position in bytes
double seconds=BASS_ChannelBytes2Seconds(midiFileStream, bytes); // translate to seconds
int timeStamp =seconds*1000; // translate to milliseconds
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDictionary *midiData = [NSDictionary dictionaryWithObjectsAndKeys:
@"fileNoteIn", @"eventType",
[NSNumber numberWithInt:note], @"note",
[NSNumber numberWithInt:velocity],@"velocity",
[NSNumber numberWithInt:timeStamp],@"timeStamp",
[NSNumber numberWithInt:position],@"position",
[NSNumber numberWithFloat:percent],@"percentPlayed",
[NSNumber numberWithInt:ticksInLoop],@"ticksInLoop",
nil];
[delegate performSelectorOnMainThread:@selector(midiFileEvent:)
withObject:midiData
waitUntilDone:NO];
[pool release];}
来自委托的
是否有可能在触发排队消息之前,NSAutoreleasePool正在删除NSDictionary实例?我哪里都不会把池子抽干的--我应该这么做吗?
- (void)simRespondToFileNote:(NSDictionary *)dictionary
{
int velocity = [[dictionary objectForKey:@"velocity"] intValue];
if (velocity == 0){
// noteOff - send it through
[delegate routeUserSimMidiEvent:dictionary];
} else {
float totalPercentCorrect = [dataSource getUserCorrectPercent];
int note = [[dictionary objectForKey:@"note"] intValue];
if (totalPercentCorrect < _userAccuracy){
float lateNoteOnTimeDelay = (dataSource.postTimeHighAccuracy - (dataSource.postTimeHighAccuracy /4)) / 1000.;
float lateNoteOffTimeDelay = lateNoteOnTimeDelay + .1; // revise
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// create noteOff data w/ velocity == 0; timeStamp == 0;
NSDictionary *midiData = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:note], @"note",
[NSNumber numberWithInt:0],@"velocity",
[NSNumber numberWithUnsignedInt:0],@"timeStamp",
nil];
[self performSelector:@selector(simLateResponseToFileNote:) withObject:dictionary afterDelay: lateNoteOnTimeDelay];
[self performSelector:@selector(simLateResponseToFileNote:) withObject:midiData afterDelay: lateNoteOffTimeDelay];
[pool release];
} else {
float lateNoteOnTimeDelay = (dataSource.postTimeLowAccuracy + (dataSource.postTimeLowAccuracy /4)) / 1000.0;
float lateNoteOffTimeDelay = lateNoteOnTimeDelay + .1; // revise
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// create noteOff data w/ velocity == 0; timeStamp == 0;
NSDictionary *midiData =[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:note], @"note",
[NSNumber numberWithInt:0],@"velocity",
nil];
// queue late noteOn
[self performSelector:@selector(simLateResponseToFileNote:) withObject:dictionary afterDelay: lateNoteOnTimeDelay];
// queue late noteOff
[self performSelector:@selector(simLateResponseToFileNote:) withObject:midiData afterDelay: lateNoteOffTimeDelay];
[pool release];
}
}}
发布于 2011-12-05 23:11:20
在simRespondToFileNote:中创建一个临时的自动释放池并不是很有用,但应该不是一个问题。您对performSelector:withObject:afterDelay:的调用将保留dictionary,直到其调用为止。如果forwardFileNoteIn:withVelocity:位于一个还没有自动释放池的线程上,您可能必须创建它,但通常在方法的顶部执行。如果这个线程已经有一个池,就没有理由在这里创建。
根据您的描述,我怀疑simLateResponseToFileNote:阻塞主线程的时间太长了。我会在那里寻找瓶颈。
发布于 2011-12-05 22:26:15
您正在将midiData对象创建到一个自动释放池中,使用midiData作为参数执行延迟的performSelector,然后耗尽池。你不觉得这里有什么问题吗?
(释放自动释放池相当于将其排出。(阅读文件)
https://stackoverflow.com/questions/8392656
复制相似问题