首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用NSAutoreleasePool冻结

使用NSAutoreleasePool冻结
EN

Stack Overflow用户
提问于 2011-12-05 22:13:48
回答 2查看 167关注 0票数 0

我正试图用我正在开发的应用程序来追踪一个冻结问题。我可能在NSAutoreleasePool的深处,正在搞砸事情。

这个应用程序正在播放一个midi文件。如果我注释掉下面使用simRespondToFileNote的“NSAutoreleasePool”代码,它不会冻结。如果我让代码运行,它将在看似随机的点冻结崩溃日志/控制台输出,这似乎并不表明问题发生在何处。

以下是程序流程:

  1. ,我正在使用Bass (C );它在自己的线程中播放midi文件。当midi事件发生时,会触发一个回调,我将midi事件数据包装在一个

中,并将其路由到主线程,以便我可以进行UI更新和其他一些事情。

下面是执行路由的代码:

代码语言:javascript
复制
- (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];

}

来自委托的

  1. 消息将使用NSDictionary实例作为param发送到另一个对象。该对象要么立即将NSDictionary实例发送到另一个对象,要么在短时间延迟后将其排队发送(使用performSelector: afterDelay:).

是否有可能在触发排队消息之前,NSAutoreleasePool正在删除NSDictionary实例?我哪里都不会把池子抽干的--我应该这么做吗?

代码语言:javascript
复制
- (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];

    }
}

}

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-05 23:11:20

simRespondToFileNote:中创建一个临时的自动释放池并不是很有用,但应该不是一个问题。您对performSelector:withObject:afterDelay:的调用将保留dictionary,直到其调用为止。如果forwardFileNoteIn:withVelocity:位于一个还没有自动释放池的线程上,您可能必须创建它,但通常在方法的顶部执行。如果这个线程已经有一个池,就没有理由在这里创建。

根据您的描述,我怀疑simLateResponseToFileNote:阻塞主线程的时间太长了。我会在那里寻找瓶颈。

票数 1
EN

Stack Overflow用户

发布于 2011-12-05 22:26:15

您正在将midiData对象创建到一个自动释放池中,使用midiData作为参数执行延迟的performSelector,然后耗尽池。你不觉得这里有什么问题吗?

(释放自动释放池相当于将其排出。(阅读文件)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8392656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档