performSelectorInBackground和detachNewThreadSelector如何工作?

lak*_*esh 6 multithreading ios

我需要执行异步函数执行,因为它阻塞了主线程,因此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];
    });
});
Run Code Online (Sandbox Code Playgroud)

我的问题是如何performSelectorInBackgrounddetachNewThreadSelector回返回主线程?你怎么知道他们已经完成了?

Rob*_*Rob 7

几点想法:

  1. 您可能希望在" 并发编程指南"中检查"远离线程迁移",这为调度队列和操作队列提供了一个引人注目的参数,这在前面的同一指南中已有讨论.

  2. 此外,当您深入研究各种异步操作时,请记住,在后台队列/线程中耗费时间,但始终将UI内容分配回主队列.我只提到这一点,因为你的任务showSpinner听起来很像UI任务,你永远不想在后台队列/线程中做.如果它有一些"昂贵的"非UI相关任务,那么很好,在后台执行,但确保UI内容被调度回主队列.

  3. 除此之外,还有其他操作队列的再现,例如块操作:

    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];
        }];
    }];
    
    Run Code Online (Sandbox Code Playgroud)

    这大致相当于GCD(调度队列)再现:

    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];
        });
    });
    
    Run Code Online (Sandbox Code Playgroud)

    操作队列和调度队列之间存在许多微妙的优点和缺点(我们不应该在这里讨论它,因为它已经在Stack Overflow上的其他地方讨论了数百次),但是这两者都让你做了比传统的更复杂的异步操作.线程编程.

  4. 如果您决定坚持使用线程与操作和/或调度队列(我不一定会推荐),您可能需要查看" 线程编程指南".


Sha*_* TK 2

要识别执行performSelectorInBackground 结束 detachNewThreadSelector,请在主线程上的线程方法末尾调用一个方法。

ExtrayNSThread提供了一个属性,isFinished它返回一个布尔值,指示接收者是否已完成执行。

例子:

[self performSelectorOnMainThread:@selector(threadMethod) 
                       withObject:nil 
                    waitUntilDone:NO];
Run Code Online (Sandbox Code Playgroud)

或者

[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.
}
Run Code Online (Sandbox Code Playgroud)