iPhone iOS rodando em discussão separada

96

Qual é a melhor maneira de executar código em um thread separado? É isso:

[NSThread detachNewThreadSelector: @selector(doStuff) toTarget:self withObject:NULL];

Ou:

    NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self
                                                                        selector:@selector(doStuff:)
                                                                          object:nil;
[queue addOperation:operation];
[operation release];
[queue release];

Tenho feito da segunda maneira, mas o Wesley Cookbook que tenho lido usa a primeira.

Mike S
fonte

Respostas:

243

Na minha opinião, a melhor maneira é com libdispatch, também conhecido como Grand Central Dispatch (GCD). Limita você ao iOS 4 e superior, mas é muito simples e fácil de usar. O código para fazer algum processamento em um thread de segundo plano e, em seguida, fazer algo com os resultados no loop de execução principal é incrivelmente fácil e compacto:

dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Add code here to do background processing
    //
    //
    dispatch_async( dispatch_get_main_queue(), ^{
        // Add code here to update the UI/send notifications based on the
        // results of the background processing
    });
});

Se você ainda não fez isso, verifique os vídeos do WWDC 2010 em libdispatch / GCD / blocks.

Jacques
fonte
Preciso que seja compatível com 3.0 :(
Mike S
1
Então, as filas de operação são provavelmente a próxima melhor solução. Além disso, certifique-se de não mergulhar na simultaneidade muito rapidamente. Tente começar escrevendo coisas com thread único e perfil para ver se você precisa usar multiencadeamento, ou se você pode projetar seu código de thread único para ser mais eficiente por conta própria. Para tarefas simples, às vezes você pode fazer tudo o que precisa com performSelector: withObject: afterDelay: e evitar todos os problemas que vêm com a programação multithread.
Jacques
Desculpe por ressuscitar isso muito mais tarde, mas se eu gerar uma chamada de método com performSelector: withObject: afterDelay, eu ainda preciso usar um NSAutoReleasePool dentro do método assíncrono? Se ele usar magicamente o pool de liberação automática principal, o performSElector: afterDelay é definitivamente uma opção mais rápida.
Mike S,
Não, porque o método está sendo executado no encadeamento principal, que possui seu próprio pool de liberação automática.
Jacques
4
@Joe Correndo o risco de dizer algo que você já sabe, você não deve adquirir o hábito de escrever código que mata threads, isso não ajudará você ou sua carreira no longo prazo. Veja esta postagem (ou muitas semelhantes) para saber por que não matar tópicos.
MikeC
1

A melhor forma de multithreading no iOS é usando GCD (Grand Central Dispatch).

//creates a queue.

dispatch_queue_t myQueue = dispatch_queue_create("unique_queue_name", NULL);

dispatch_async(myQueue, ^{
    //stuffs to do in background thread
    dispatch_async(dispatch_get_main_queue(), ^{
    //stuffs to do in foreground thread, mostly UI updates
    });
});
Kusal Shrestha
fonte
0

Eu tentaria todas as técnicas que as pessoas postaram e ver qual é a mais rápida, mas acho que essa é a melhor maneira de fazer isso.

[self performSelectorInBackground:@selector(BackgroundMethod) withObject:nil];
Bobby
fonte
isso inicia o thread em uma prioridade baixa. Usar o gcd é a melhor maneira de encadear.
Karsten