NSThread с ошибкой _NSAutoreleaseNoPool

У меня есть метод сохранения файлов в Интернете, он работает, но очень медленно. Затем я хотел бы сделать пользовательский интерфейс более плавным, поэтому я создаю NSThread для обработки медленной задачи.

Я вижу список ошибок, например:

_NSAutoreleaseNoPool(): Object 0x18a140 of class NSCFString autoreleased with no pool in place - just leaking

Без NSThread я вызываю метод так:

[self save:self.savedImg];

И я использовал следующее, чтобы использовать NSThread для вызова метода:

NSThread* thread1 = [[NSThread alloc] initWithTarget:self
                                        selector:@selector(save:)
                                              object:self.savedImg];
[thread1 start];

Спасибо.


person BlueDolphin    schedule 30.10.2008    source источник


Ответы (5)


Ну, во-первых, вы оба создаете новый поток для своего кода сохранения, а затем асинхронно используете NSUrlConnection. NSUrlConnection в своей собственной реализации также будет выделять другой поток и вызывать вас обратно в ваш вновь созданный поток, что в основном не то, что вы пытаетесь сделать. Я предполагаю, что вы просто пытаетесь убедиться, что ваш пользовательский интерфейс не блокируется во время сохранения...

NSUrlConnection также имеет синхронную версию, которая будет блокироваться в вашем потоке, и было бы лучше использовать ее, если вы хотите запустить свой собственный поток для выполнения каких-либо действий. Подпись

+ sendSynchronousRequest:returningResponse:error:

Затем, когда вы получите ответ, вы можете перезвонить в свой поток пользовательского интерфейса. Что-то вроде ниже должно работать:

- (void) beginSaving {
   // This is your UI thread. Call this API from your UI.
   // Below spins of another thread for the selector "save"
   [NSThread detachNewThreadSelector:@selector(save:) toTarget:self withObject:nil];    

}

- (void) save {
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];  

   // ... calculate your post request...
   // Initialize your NSUrlResponse and NSError

   NSUrlConnection *conn = [NSUrlConnection sendSyncronousRequest:postRequest:&response error:&error];
   // Above statement blocks until you get the response, but you are in another thread so you 
   // are not blocking UI.   

   // I am assuming you have a delegate with selector saveCommitted to be called back on the
   // UI thread.
   if ( [delegate_ respondsToSelector:@selector(saveCommitted)] ) {
    // Make sure you are calling back your UI on the UI thread as below:
    [delegate_ performSelectorOnMainThread:@selector(saveCommitted) withObject:nil waitUntilDone:NO];
   }

   [pool release];
}
person keremk    schedule 30.10.2008
comment
случай и подпись закрыты при вызове синхронизации, это должно быть NSURLConnection *conn = [NSURLConnection sendSyncronousRequest:postRequest returnResponse:&response error:&error]; - person Jehiah; 30.06.2009

В основном вам нужно создать пул авторелиза для потока. Попробуйте изменить метод сохранения следующим образом:

- (void) save:(id)arg {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    //Existing code

    [pool drain];
}

Вы не заметите, что приведенное выше не вызывает релиз в NSAutoreleasePool. Это особый случай. Для NSAutoreleasePool сток эквивалентен выпуску при работе без GC и преобразуется в подсказку сборщику, что, возможно, стоит запустить сбор.

person Louis Gerbarg    schedule 30.10.2008

Возможно, вам потребуется создать цикл выполнения. Я добавлю к решению Луи:

BOOL done = NO;

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[NSRunLoop currentRunLoop];

// Start the HTTP connection here. When it's completed,
// you could stop the run loop and then the thread will end.

do {
    SInt32 result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES);
    if ((result == kCFRunLoopRunStopped) || (result == kCFRunLoopRunFinished)) {
        done = YES;
    }
} while (!done);

[pool release];
person Chris Lundie    schedule 30.10.2008

В потоке вам нужно создать новый пул автоматического освобождения, прежде чем делать что-либо еще, иначе сетевые операции будут иметь проблемы, как вы видели.

person Kendall Helmstetter Gelner    schedule 30.10.2008

Не вижу причин использовать для этого потоки. Простое выполнение этого асинхронно в цикле выполнения должно работать без блокировки пользовательского интерфейса.

Доверьтесь циклу выполнения. Это всегда проще, чем многопоточность, и обеспечивает тот же результат (никогда не блокируемый пользовательский интерфейс).

person Peter Hosey    schedule 31.10.2008