performSelectorInBackground和detachNewThreadSelector如何工作?

6
我需要执行异步函数,因为它会阻塞主线程,导致UI不可用。
在查看stackoverflow上的问题后,我知道有三种方法可以执行异步函数。
一个例子:
[NSThread detachNewThreadSelector:@selector(showSpinner:) toTarget:self withObject:self.view];
// or 
[self performSelectorInBackground:@selector(showSpinner:) withObject:self.view];
// or 
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(showSpinner:) object:self.view];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:invOperation];
// or 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        [self showSpinner:self.view];
    });
});

我的问题是,performSelectorInBackgrounddetachNewThreadSelector如何返回到主线程?你如何知道它们已经完成?

1
@Rob 谢谢。请把你的答案添加上去,我会点赞的。 - lakshmen
2个回答

7
一些想法:
  1. You might want to check Migrating Away From Threads in the Concurrency Programming Guide, which makes a compelling argument for dispatch queues and operation queues, which are discussed earlier in that same guide.

  2. Also, as you delve into various asynchronous operations, remember, do time consuming stuff in background queues/threads, but always dispatch UI stuff back to the main queue. I only mention that because your task, showSpinner sounds a lot like a UI task, which you would never want to do in a background queue/thread. If it has some "expensive" non-UI related tasks, then fine, do that in the background, but make sure the UI stuff gets dispatched back to the main queue.

  3. There are, as an aside, other renditions of the operations queues, e.g., block operations:

    NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
    [opQueue addOperationWithBlock:^{
        // do some slow stuff in the background here
    
        // ok, now do UI stuff in the main queue
    
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self showSpinner:self.view];
        }];
    }];
    

    This is roughly equivalent to the GCD (dispatch queue) rendition:

    dispatch_queue_t dispatchQueue = dispatch_queue_create("com.ramshad.app", 0);
    dispatch_async(dispatchQueue, ^{
        // do some slow stuff in the background here
    
        // ok, now do UI stuff in the main queue
    
        dispatch_async(dispatch_get_main_queue(), ^{
            [self showSpinner:self.view];
        });
    });
    

    There are tons of subtle pros and cons between the operation queues and dispatch queues (which we should not get into here because it's been discussed hundreds of times elsewhere on Stack Overflow), but both let you do surprisingly rich asynchronous operations with less complexity than traditional thread programming.

  4. If you decide to stick with threads versus operation and/or dispatch queues (which I wouldn't necessarily recommend), you might want to check out the Threading Programming Guide.


2
为了确定performSelectorInBackgrounddetachNewThreadSelector的执行结束,需要在主线程上调用线程方法末尾的方法。
此外,NSThread提供了一个属性isFinished,返回一个布尔值,指示接收器是否已完成执行。 示例:
[self performSelectorOnMainThread:@selector(threadMethod) 
                       withObject:nil 
                    waitUntilDone:NO];

或者

[NSThread detachNewThreadSelector:@selector(threadMethod) 
                         toTarget:self 
                       withObject:nil];

-(void)threadMethod{

    //here your implementation code
    //here call the end notification method.
    [self performSelectorOnMainThread:@selector(ThreadExecutionDone) 
                           withObject:nil 
                        waitUntilDone:YES];
}

-(void)ThreadExecutionDone{
    //end of the performSelectorInBackground or detachNewThreadSelector.
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接