DrawInRect deve: para um contexto separado ser executado no thread principal?

[atualização: este problema foi resolvido; o problema não estava emdrawInRect: mas emUIGraphicsBeginImageContext()]

No meu aplicativo, estou pegando um monte de imagens grandes, cortando-as no tamanho de miniaturas e armazenando as miniaturas para visualização.

Observe que estou fazendo isso em um contexto de imagem separado - isso énão sobre redesenhar umUIView isso está na tela.

Esse código é bastante intenso, então eu estou executando-o em um thread separado. O dimensionamento real se parece com isso e é uma implementação de categoria além deUIImage:

- (UIImage *) scaledImageWithWidth:(CGFloat)width andHeight:(CGFloat)height
{
    CGRect rect = CGRectMake(0.0, 0.0, width, height);
    UIGraphicsBeginImageContext(rect.size);
    [self drawInRect:rect]; // <-- crashing on this line
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return scaledImage;
}

Isso é chamado de um método separado, que percorre as imagens por sua vez e faz o processamento. A chamada real para o método acima se parece com isso:

UIImage *small = [bigger scaledImageWithWidth:24.f andHeight:32.f];

Isso tudo funciona na maioria das vezes, mas ocasionalmente recebo umaEXC_BAD_ACCESS.

Backtrace:

#0  0x330d678c in ripc_RenderImage ()
#1  0x330dd5aa in ripc_DrawImage ()
#2  0x300e3276 in CGContextDelegateDrawImage ()
#3  0x300e321a in CGContextDrawImage ()
#4  0x315164c8 in -[UIImage drawInRect:blendMode:alpha:] ()
#5  0x31516098 in -[UIImage drawInRect:] ()
#6  0x0000d6e4 in -[UIImage(Scaling) scaledImageWithWidth:andHeight:] (self=0x169320, _cmd=0x30e6e, width=48, height=64) at /Users/me/Documents/svn/app/trunk/Classes/UIImage+Scaling.m:20
#7  0x00027df0 in -[mgMinimap loadThumbnails] (self=0x13df00, _cmd=0x30d05) at /Users/me/Documents/svn/app/trunk/Classes/mgMinimap.m:167
#8  0x32b15bd0 in -[NSThread main] ()
#9  0x32b81cfe in __NSThread__main__ ()
#10 0x30c8f78c in _pthread_start ()
#11 0x30c85078 in thread_start ()

[atualização 4] Quando executo isso no Simulador, e esse problema ocorre, o console mostra adicionalmente o seguinte:

// the below is before loading the first thumbnail
<Error>: CGContextSaveGState: invalid context
<Error>: CGContextSetBlendMode: invalid context
<Error>: CGContextSetAlpha: invalid context
<Error>: CGContextTranslateCTM: invalid context
<Error>: CGContextScaleCTM: invalid context
<Error>: CGContextDrawImage: invalid context
<Error>: CGContextRestoreGState: invalid context
<Error>: CGBitmapContextCreateImage: invalid context
// here, the first thumbnail has finished loading and the second one
// is about to be generated
<Error>: CGContextSetStrokeColorWithColor: invalid context
<Error>: CGContextSetFillColorWithColor: invalid context

Meu pressentimento é que, ocasionalmente, acabo tentandodrawInRect: enquanto o sistema operacional também está tentando desenhar algo, o que resulta, ocasionalmente, em um acidente. Sempre presumi que, desde que você não desenhe na tela real, isso é aceitável - não é esse o caso? Ou, se for o caso, alguma idéia do que pode estar causando isso?

Atualização (r2): esqueci de mencionar que este aplicativo está sendo executado com restrições de memória bastante severas (tenho muitas imagens carregadas a qualquer momento e elas são trocadas / desativadas), portanto, este pode ser um caso de execução falta de memória (leia - não é). Não tenho certeza de como verificar isso, no entanto, portanto, pensamentos sobre isso também serão bem-vindos. Eu verifiquei isso reduzindo severamente o número de imagens sendo carregadas e adicionando uma verificação para garantir que elas sejam desalocadas adequadamente (elas são e a falha ainda ocorre).

Atualização 3: Eu pensei ter encontrado o problema. Abaixo está a resposta que escrevi, antes que o acidente acontecesse novamente:

O código (depois que eu postei essa pergunta) ocasionalmente começava a sair com o código de saída0e, às vezes, com o código de saída10 (SIGBUS). 0 significa "sem erro", o que foi extremamente estranho.10 parece significar um pouco de tudo, o que também foi inútil. odrawInRect: A ligação foi uma grande dica, no entanto, quando o acidente aconteceu lá.

O loop para obter as miniaturas estava gerando muitas imagens liberadas automaticamente. Eu tinha um pool de autorelease, mas ele envolvia todo o loop for. Adicionei um segundo pool de autorelease dentro dofor ciclo:

- (void)loadThumbnails
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    for (...) {
        NSAutoreleasePool *cyclePool = 
           [[NSAutoreleasePool alloc] init]; // <-- here
        UIImage *bigger = ...;
        UIImage *small = [bigger scaledImageWithWidth:24.f andHeight:32.f];
        UIImage *bloated = [i scaledImageWithWidth:48.f andHeight:64.f];
        [cyclePool release]; // <-- ending here
    }
    [pool release];
}

Eu pensei que o problema acima corrigia o problema, até que eu executei o aplicativo e ele travou com o "código de saída 0" novamente pouco antes. Voltar para a prancheta ...

questionAnswers(3)

yourAnswerToTheQuestion