文档章节

Objective-C 后台线程 和 NSOperationQueue

木木情深
 木木情深
发布于 2014/02/19 23:45
字数 1065
阅读 646
收藏 0
  1. 后台线程

    简单操作,无需创建线程时,可以使用一下函数(以UILabel 为例):

    [myLabel performSelector:@selector(setText:) withObject:@"hello" afterDelay:0.1f];

    代替平时的操作:[myLabel setText:@"hello"];

    1)创建线程:执行线程函数,将函数要执行的任务从主界面线程中分离出来

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

    -(void)listenForRequests

    {

          @autoreleasepool

          {

                //doSomething 

                ........            

          }

    }

    注意:线程函数内创建的任何对象在函数执行完成以后不会得到协防,为防止内存泄漏,在线程函数中需使用@autoreleasepool{}进行内存管理

           RunLoop
    说到 NSThread 就不能不说起与之关系相当紧密的 NSRunLoop。Run loop 相当于 win32 里面的消息循环机制,它可以让你根据事件/消息(鼠标消息,键盘消息,计时器消息等)来调度线程是忙碌还是闲置。
    系统会自动为应用程序的主线程生成一个与之对应的 run loop 来处理其消息循环。在触摸 UIView 时之所以能够激发 touchesBegan/touchesMoved 等等函数被调用,就是因为应用程序的主线程在 UIApplicationMain 里面有这样一个 run loop 在分发 input 或 timer 事件。

    2) 使用通知中心通知主线程更新界面:在线程函数中发送消息,在主线程中注册监听消息

        -(void)listenForRequests

    {

          @autoreleasepool

          {

                //doSomething 

               ........         

               [[NSNotificationCenter defaultCenter] postNotificationName:@"updateUI" object: obj];  

          }

    }

    主线程注册监听:

             [[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(handlePost:) name:@"updateUI"  object:nil];

    -(void)handlePost:(NSNotification *)notify

    {

          id obj = [notify object];

          [self  performSelectorOnMainThread:@selector(update:) withObject:obj waitUntilDone:YES];

    }

    注: 这里接收到消息后,有必要的话,可以再开启线程来处理相关操作。

    附: 虽然传统的 NSThread 也可以进行多线程的管理,但是需要处理线程的声明周期,还要考虑线程同步、加锁等问题,会操作一定程度上的性能开销。

  2. 并发执行后台类 NSOperationQueue,分为4步来操作

    1)定义一个操作类

         a. 先定义一个回调接口,在任务完成后发送通知

             @protocal LongTaskOperationProtocal<NSObject>

             -(void) longTaskOperationFinished:(LongTaskOperation *)op;//接收 operation --LongTaskOperation 进行相关操作

             @end

         b. 定义一个操作类

            方法1. NSOperation子类 NAInvocationOperation

               NAInvocationOperation *operation = [[NSInvocationOperation alloc]initWitTarget:self selector:@selector(listenForRequets) object:obj];

             // 与当前线程同步执行代码   [operation star];

            // 异步执行需加入到 NSOperationQueue 中

             NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];

             [operationQueue addOperation:operation];

            方法2. NSOperation子类 NABlockOperation

            // 并发执行一个线程

          NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"执行线程。");

    }];

    [blockOperation start];

          // 并发执行多个线程

         NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{

        NSLog(@"执行线程:%@",[NSThread currentThread]);

    }];

    [blockOperation addExecutionBlock:^{

        NSLog(@"执行一个并发线程线程:%@",[NSThread currentThread]);

    }];

    [blockOperation start];//并发的执行多个操作,分别在不同的线程中操作


  注: 线程完成后执行操作  :  operation.completionBlock =  ^(){};


        方法3. 自定义一个NSOperation的子类

         #import  "LongTaskOperationProtocal.h"

         @interface LongTaskOperation:NSOperation 

         {

               @private

                  NSString *imgFilePath;

         }

         @property (nonatomic,assign) id<LongTaskOperationProtocal> delegate;

               -(id)initWithPath:(NSString *)aPath;

                @end

        2)编写操作类的main()函数

                // LongTaskOperation.m   

                -(id)initWithPath:(NSString *)aPath

        {

            if (self == [super init]) {

        

            }

            return self;

        }

 

                //重写 NSOperation mian方法          

        -(void)main

        {

            if (!self.isCancelled) {

                @autoreleasepool {

                //do you back-end task

            

                if (!self.isCancelled &&self.delegate) {

                    [self.delegate longTaskOperationFinished:self];

                }

                        

              }

           }

        }

    注意:mian函数中一定要 使用独立的 autoreleasepool 来管理操作类中的变量,否则会造成内存泄漏。


    3)在需要进行耗时操作的类中创建操作类对象,并加入NSOperationQueue        

    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    [queue setMaxConcurrentOperationCount:[[NSProcessInfo processInfo]        activeProcessorCount] + 1];//设置线程队列中的最多线程数

    LongTaskOperation *operation = [[LongTaskOperation alloc]initWithPath:@"string"];

    operation.delegate = self;

    [queue addOperation:operation];

    operation = nil;


//注意:操作加入队列后,要立即释放操作对象。


    4)在进行耗时操作的类中定义操作完成函数

          -(void) longTaskOperationFinished:(LongTaskOperation *)op

           {........}

附:程序不需要队列时,释放队列

       [ queue cancelAllOperations];

      queue = nil;














© 著作权归作者所有

木木情深
粉丝 37
博文 189
码字总数 26451
作品 0
广州
程序员
私信 提问
牛客网 iOS 题 107-126

### 牛客网 iOS 题 107-126 107.NSRunLoop 以下描述错误的是( ) RunLoop 并不是由系统自动控制的 有三类对象可以被 RunLoop 监控:sources,timers,observers 线程是默认启动 RunLoop 的 ...

木佥
2018/05/12
0
0
iOS之[多线程:NSOperation]

NSOperation :fa-exclamation-triangle:以下是你需要考虑使用 NSOperation 的一些理由: 1.当你需要取消线程任务时,GCD 无法提供取消任务的操作。而 NSOperation 提供了取消任务的操作; 2.当...

言筱羽
2015/11/23
120
0
关于iOS多线程

关于iOS多线程 原文地址:http://www.jianshu.com/p/0b0d9b1f1f19 在这篇文章中,我将为你整理一下 iOS 开发中几种多线程方案,以及其使用方法和注意事项。当然也会给出几种多线程的案例,在实...

法斗斗
2016/03/10
15
0
iOS多线程编程之NSOperation和NSOperationQueue的使用

目录(?)[-] iOS多线程编程之NSThread的使用 使用 NSOperation的方式有两种 一种是用定义好的两个子类 另一种是继承NSOperation NSInvocationOperation例子 第二种方式继承NSOperation 如何控...

malawo
2013/09/05
30
0
Objective-C-NSOperation

NSOpseration是抽象基类,所以要用子类实现它的方法。(内部使用gcd实现) 1.一个NSOperation 就代表一个任务,任务的代码分装在block里或者函数里。 OC提供子类: NSInvocztionOperation:任...

BKF_
2016/03/03
9
0

没有更多内容

加载失败,请刷新页面

加载更多

华为手机翻译功能怎么使用?这三种方法请务必收藏

华为手机翻译功能怎么使用?在我们的生活中会经常遇到翻译问题,许多外语不好的朋友该怎么办呢?华为手机已经为我们解决了这个问题,今天小编就教大家学会使用华为手机中的三种翻译技巧,需要...

翻译小天才
10分钟前
2
0
企业服务软件开发中需要注意的三个问题

在开发企业服务软件时,我们需要分为:业务需求、用户需求、产品需求,三大需求层次,三个层次互相关联,企业服务软件开发首先要服务业务,需要满足业务的需求,再关注用户体验,也就是用户需...

积木创意科技
13分钟前
2
0
C++容器底层数据结构

内置数组: int arr[10][10];memset(arr,0,10*10*sizeof(int)); //初始化int tmp[10][10];memcpy(arr, tmp, 10 * 10 * sizeof(int));//拷贝 void *memcpy(void *destin, void *source,......

SibylY
13分钟前
2
0
Dubbo-自适应拓展机制

背景 在 Dubbo 中,很多拓展都是通过 SPI 机制进行加载的,比如 Protocol、Cluster、LoadBalance 等,这些都是Dubbo的基础组件。这些基础组件的拓展不是在系统框架启动阶段被加载,而是拓展方...

rock-man
42分钟前
6
0
Kali安装fcitx输入法(五笔)

安装fcitx > sudo apt-get install fcitx-rime fcitx-config-gtk3 重启 > sudo reboot fcitx配置 效果就是这样 配置输入法切换 系统设置...

yeahlife
44分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部