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];
    });
});

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

4

2 回答 2

7

几个想法:

  1. 您可能想查看并发编程指南中的Migrating Away From Threads ,它为调度队列和操作队列提供了一个令人信服的论据,这在同一指南的前面已经讨论过了。

  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];
        }];
    }];
    

    这大致相当于 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];
        });
    });
    

    操作队列和调度队列之间有很多微妙的优点和缺点(我们不应该在这里讨论,因为它在 Stack Overflow 的其他地方已经讨论了数百次),但它们都可以让您以比传统方式更简单的复杂性来完成令人惊讶的丰富异步操作线程编程。

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

于 2013-03-13T04:57:11.737 回答
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.
}
于 2013-03-13T03:44:44.037 回答