objective -c 异步处理

本文介绍了Objective-C中实现异步处理的几种方法,包括使用NSThread创建新线程、在主线程与后台之间进行通信、利用NSLock进行线程同步以及通过Grand Central Dispatch (GCD)调度任务。还提到了使用@synchronized关键字进行线程同步的区别,并给出了使用GCD和NSOperationQueue的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、使用NSThread开辟新线程

使用NSThread的类方法:[NSThread detachNewThreadSelector: @selector(myNewThreadMethod:) toTarget: someObject wothObject: object]

则会调用方法[someObject myNewThreadMethod:]方法

2、主线程与后台之间的通信

使用NSObject的performSelectorOnMainThread: withObject: waitUntilDone:方法执行主线程中的方法

3、应用使用了多个线程,但有时需要确保两个线程不会使用同一代码块,否则应用可能产生冲突,导致用户产生混乱或者文件被多次访问,

解决方法:(1)使用NSLock让其他线程等待,直到当前线程处理完关键代码块为止,然后下一个线程再完成它的动作。比如按一下按钮,进度条从0到100,连续按两次按钮,进度条从0到100后,再变为0到100,而不是中断。

首先,将NSLock对象作为属性添加到视图控制器中; @property(strong) NSLock *threadLock;

@synthesize threadLock;

然后,实例化NSLock对象; self.threadLock = [[NSLock alloc] init];

最后,在需要锁定的代码块前,添加[self.threadLock lock]; 在可以释放的地方,添加[self,threadLock unlock];

例如:

 -void bigTask
{
    [self.threadLock lock]; 
    for(int i = 0;i <40000;i++)
    {
        NSString *newStr = [NSString stringWithFormat:@"i=%i",i];

        NSLog(@"%@",newStr);

   }

[self.threadLock unlock];
}
解决办法(2)使用@synchronized锁定线程

想要保证在同一时刻只有一个线程会使用某个代码块,可将整个代码块放在以@synchronized指令开头的花括号中。

 -void bigTask
{ 
  @synchronized(self){
    for(int i = 0;i <40000;i++)
    {
        NSString *newStr = [NSString stringWithFormat:@"i=%i",i];

        NSLog(@"%@",newStr);

   } 

   }

}

@synchronized指令完成的多线程行为,比如按一下按钮,进度条从0到100,连续按两次按钮,进度条从0到100后,再变为0到100,而不是中断。

这与NSLock有何区别? 有待查找答案。。。。


其他异步方法:

4、使用Grand Central Dispatch(GCD)进行异步处理

GCD在OSX10.6与iOS4中被引入进来。GCD需要使用名为”块“的编程技术,块是可看做对象的代码区域,这意味着可以在花括号之间放置代码行,然后将它们看做对象。

通常情况下,块被用作方法的参数。

GCD使用块而不是方法(带有@selector指令),这意味着无须将希望执行的代码都放到新方法中。相反,需要从调用GCD函数的函数中将代码作为参数传递给GCD函数,

使用GCD函数dispatch_async可以完成任务,比如:

-(void)bigTaskAction
{
    [self.myActivityIndicator startAnimating];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^{
    int updateUIWhen = 1000;
    for(int i = 0;i<10000,i++)
    {
         NSLog(@"i = %@",i);
         if(i == updateUIWhen){
             float f = (float)i/10000;
             NSNumber *percentDone = [NSNumber numberWithFloat:f];
             dispatch_sync(dispatch_get_main_queue(),^{
             [self.progressView setProgress:[percentDone floatValue] animated:YES];
             });
             updateUIWhen += 1000;
         }
     }
 
      dispatch_sync(dispatch_get_main_queue(),^{
           [self.progressView setProgress:1.0 animated:YES];
           self.myActivityIndicator stopAnimating];
       });
 
});
}
看GCD函数:
<span style="background-color: rgb(255, 255, 153);">dispatch_async</span>(<span style="background-color: rgb(102, 255, 255);">dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0</span><span style="color:#33ccff;">)</span>,<span style="background-color: rgb(204, 51, 204);">^{}</span>);
第一部分是函数名dispatch_async,这是个会异步执行的GCD函数,另外有名为<span style="font-family: Arial, Helvetica, sans-serif;">dispatch_sync的类似函数会同步执行代码;</span>
<span style="font-family: Arial, Helvetica, sans-serif;">函数的第一个参数是分发队列:</span><span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;">dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0) 这个</span><pre name="code" class="objc"><span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;">dispatch_get_global_queue函数会一次返回该应用默认的分发队列。</span>
<span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;">注意:GCD支持名为代码队列的概念,队列会被调度以在下一个可用的处理器上执行。在使用GCD时,需要指定将代码放在哪个队列中。这里使用的是默认队列,默认队列也可以用于后台处理,还可以使用主队列,主队列类似于用户界面的主线程。</span>
对于GCD分发队列来说,在使用dispatch_async时无法确定代码块的执行顺序,系统会选择最高效的方式。因此,如果顺序很重要,可以使用dispacth_sync。

5、在GCD中使用顺序队列
使用GCD进行异步处理的时候,要求块每次都按照它们在代码中出现的顺序执行,可以使用GCD顺序队列加载代码块,
这些代码块会按照它们在队列中的顺序执行。可以通过GCD函数dispatch_queue_create(DISPATCH_QUEUE_SERIAL,0)来创建顺序队列。
确保顺序队列位于所服务对象的生命周期范围内。
首先,创建顺序队列属性: @property(assign) dispatch_queue_t serialQueue; @synthesize serialQueue;
在viewDidLoad中 self.serialQueue = dispatch_queue_create<span style="font-family: Arial, Helvetica, sans-serif;">(DISPATCH_QUEUE_SERIAL,0);</span><pre name="code" class="objc">使用时,


-(void)bigTaskAction
{
    dispatch_async(self.serialQueue,^{
       dispatch_sync(dispatch_get_main_queue(),^{
          [self.myActivityIndicator startAnimating];
       }); 
<pre name="code" class="objc">    int updateUIWhen = 1000;
    for(int i = 0;i<10000,i++)
    {
         NSLog(@"i = %@",i);
         if(i == updateUIWhen){
             float f = (float)i/10000;
             NSNumber *percentDone = [NSNumber numberWithFloat:f];
             dispatch_sync(dispatch_get_main_queue(),^{
             [self.progressView setProgress:[percentDone floatValue] animated:YES];
             });
             updateUIWhen += 1000;
         }
     }
 
      dispatch_sync(dispatch_get_main_queue(),^{
           [self.progressView setProgress:1.0 animated:YES];
           self.myActivityIndicator stopAnimating];
       });

    });
}
    
6、使用NSOperationQueue实现异步处理

NSOperationQueue表示待执行的代码队列。可以通过NSOperationQueue在后台运行代码或是在主队列中运行以响应用户界面动作。

NSOperationQueue可以通过多种方式来添加代码。如果操作系统支持块,则可以通过addOperationWithBlock:方法直接向队列中添加代码,

否则,需要将待执行的代码放在NSOperation子类中。

例如使用块:

首先,添加局部实例: NSOperationQueue *serialQueue; NSOperationQueue * mainQueue;

在viewDidLoad中实例化它们: mainQueue = [NSOperationQueue  mainQueue];

serialQueue = [[NSOperationQueue  alloc] init];

serialQuaue.maxConcurrentOperationCount = 1;

-(void)bigTaskAction
{
    [serialQueue addOperationWithBlock:^{ 
       [mainQueue addOperationWithBlock:^{
          [self.myActivityIndicator startAnimating];
       }]; 
    int updateUIWhen = 1000;
    for(int i = 0;i<10000,i++)
    {
         NSLog(@"i = %@",i);
         if(i == updateUIWhen){
             float f = (float)i/10000;
             NSNumber *percentDone = [NSNumber numberWithFloat:f];
             [mainQueue addOperationWithBlock:^{
                 [self.progressView setProgress:[percentDone floatValue] animated:YES];
             }];
             updateUIWhen += 1000;
         }
     }
 
      [mainQueue addOperationWithBlock:^{
           [self.progressView setProgress:1.0 animated:YES];
           self.myActivityIndicator stopAnimating];
       }];
    }];
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值