6.12 Running Tasks Synchronously with Operations

本文介绍了使用NSInvocationOperation和NSBlockOperation执行同步任务的方法,并提供了创建自定义NSOperation子类实现异步执行的示例。

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


如果你想执行一系列的同步任务,你可以这么做


- (void) simpleOperationEntry:(id)paramObject{

    NSLog(@"Parameter Object = %@", paramObject);

    NSLog(@"Main Thread = %@", [NSThreadmainThread]);

    NSLog(@"Current Thread = %@", [NSThreadcurrentThread]);

}


NSInvocationOperation *simpleOperation;


-(void)test6_12

{

   NSNumber *simpleObject = [NSNumbernumberWithInteger:123];

    simpleOperation = [[NSInvocationOperationalloc] initWithTarget:self

 selector:@selector(simpleOperationEntry:)

                                                            object:simpleObject];

    [simpleOperationstart];

    

}

输出:


2014-03-11 09:56:13.738 cookbook[478:a0b] Parameter Object = 123

2014-03-11 09:56:13.739 cookbook[478:a0b] Main Thread = <NSThread: 0x8920550>{name = (null), num = 1}

2014-03-11 09:56:13.739 cookbook[478:a0b] Current Thread = <NSThread: 0x8920550>{name = (null), num = 1}


就如NSInvocationOperation名字所表明的那样,其主要职责是调用一个对象内部的方法,也是使用operation最直接的方法。下一节将学到如何使得operation与调用线程异步执行。


接下来我们来看下block方式的:


-(void)test6_12_1

{

   NSBlockOperation *simpleOperation;

    simpleOperation = [NSBlockOperationblockOperationWithBlock:^{

        NSLog(@"Main Thread = %@", [NSThreadmainThread]);

        NSLog(@"Current Thread = %@", [NSThreadcurrentThread]);

       NSUInteger counter = 0;

       for (counter = 0; counter <1000;

             counter++){

           NSLog(@"Count = %lu", (unsignedlong)counter);

        } }];

    /* Start the operation */

    [simpleOperationstart];

    /* Print something out just to test if we have to wait

     for the block to execute its code or not */

    NSLog(@"Main thread is here");

}

输出:


2014-03-11 10:14:38.816 cookbook[530:a0b] Main Thread = <NSThread: 0x8961430>{name = (null), num = 1}

2014-03-11 10:14:38.817 cookbook[530:a0b] Current Thread = <NSThread: 0x8961430>{name = (null), num = 1}

2014-03-11 10:14:38.817 cookbook[530:a0b] Count = 0

2014-03-11 10:14:38.817 cookbook[530:a0b] Count = 1

。。。。。。。


2014-03-11 10:14:39.302 cookbook[530:a0b] Count = 997

2014-03-11 10:14:39.303 cookbook[530:a0b] Count = 998

2014-03-11 10:14:39.303 cookbook[530:a0b] Count = 999

2014-03-11 10:14:39.304 cookbook[530:a0b] Main thread is here


这说明,如果我们在主线程中启动了operation,它就会在主线程中执行。这当然是个不好的做法,繁重的事情不应该由主线程在干。

除了上面两个opération,我们也可以自己创建NSOperation的子类。在创建之前,我们必须明白几点

1,如果你不想用operation queue,你就应该在start方法里面detach子线程来执行。

如果你即不想用opération queue也不想你的opération异步执行,好吧,那你就直接在start里面调下main方法。

2,必须重写两个方法:isExecuting和isFinished,而且返回值必须是线程安全的。再通过kvo通知监听者状态的改变。

3,在main方法中实现自动释放池,因为你这个opération将来可能加到opération queue中。你应该确保你的opération可以在这两种方式下运行:手动start或opération queue start。

4,你应该设计一个初始化方法,所有别的初始化方法,包括默认的初始化方法都来调用你这个新的初始化方法。新的初始化方法应该是参数最多的,别人在调用它时能够传入正确的入参。


好,来个例子:

头文件


#import <Foundation/Foundation.h>


@interface CountingOperation :NSOperation

/* Designated Initializer */

- (id) initWithStartingCount:(NSUInteger)paramStartingCount

                 endingCount:(NSUInteger)paramEndingCount;


@end


.m文件


#import "CountingOperation.h"


@implementation CountingOperation


NSUInteger startingCount;

NSUInteger endingCount;

BOOL finished;

BOOL executing;


- (id) init {

    return([selfinitWithStartingCount:0

                           endingCount:1000]);

}


- (id)initWithStartingCount:(NSUInteger)paramStartingCount

endingCount:(NSUInteger)paramEndingCount{

   self = [super init];

   if (self !=nil){

        /* Keep these values for the main method */

        startingCount = paramStartingCount; endingCount = paramEndingCount;

    }

    return(self);

}

- (void) start {

    /* If we are cancelled before starting, then

     we have to return immediately and generate the required KVO notifications */

   if ([self isCancelled]){

        /* If this operation *is* cancelled */

        /* KVO compliance */

        [selfwillChangeValueForKey:@"isFinished"];

        finished =YES;

        [self didChangeValueForKey:@"isFinished"];

       return;

    }else {

        /* If this operation is *not* cancelled */

        /* KVO compliance */

        [self willChangeValueForKey:@"isExecuting"];

       executing = YES;

        /* Call the main method from inside the start method */

        [self didChangeValueForKey:@"isExecuting"];

        [self main];

    }

}


- (void) main {

   @try {

        /* Here is the autorelease pool */

        @autoreleasepool {

            /* Keep a local variable here that must get set to YES whenever we are done with the task */

           BOOL taskIsFinished = NO;

            /* Create a while loop here that only exists

             if the taskIsFinished variable is set to YES or the operation has been cancelled */

           while (taskIsFinished == NO && [self isCancelled] == NO){

                /* Perform the task here */

                NSLog(@"Main Thread = %@", [NSThread mainThread]);

                NSLog(@"Current Thread = %@", [NSThread currentThread]);

                NSUInteger counter = startingCount;

               for (counter = startingCount;

                     counter < endingCount;

                     counter++){

                    NSLog(@"Count = %lu", (unsignedlong)counter);

                }

                /* Very important. This way we can get out of the

                 loop and we are still complying with the cancellation rules of operations */

               taskIsFinished = YES; }

            /* KVO compliance. Generate the required KVO notifications */

            [selfwillChangeValueForKey:@"isFinished"];

            [selfwillChangeValueForKey:@"isExecuting"];

           finished = YES;

            executing =NO;

            [self didChangeValueForKey:@"isFinished"];

            [self didChangeValueForKey:@"isExecuting"];

        }

    }

   @catch (NSException * e) {

        NSLog(@"Exception %@", e);

    }

}

- (BOOL) isFinished{

    /* Simply return the value */

   return(finished);

}

- (BOOL) isExecuting{

    /* Simply return the value */

   return(executing);

}

@end


调用方法

-(void)test6_12_2

{

   CountingOperation *simpleOperation;

    

    simpleOperation = [[CountingOperationalloc] initWithStartingCount:0endingCount:1000];

    [simpleOperationstart];

    NSLog(@"Main thread is here");

}

输出:


2014-03-11 11:29:29.248 cookbook[593:a0b] Main Thread = <NSThread: 0x8944950>{name = (null), num = 1}

2014-03-11 11:29:29.248 cookbook[593:a0b] Current Thread = <NSThread: 0x8944950>{name = (null), num = 1}

2014-03-11 11:29:29.248 cookbook[593:a0b] Count = 0

2014-03-11 11:29:29.249 cookbook[593:a0b] Count = 1

。。。。。。。。

2014-03-11 11:29:29.743 cookbook[593:a0b] Count = 996

2014-03-11 11:29:29.743 cookbook[593:a0b] Count = 997

2014-03-11 11:29:29.743 cookbook[593:a0b] Count = 998

2014-03-11 11:29:29.744 cookbook[593:a0b] Count = 999

2014-03-11 11:29:29.744 cookbook[593:a0b] Main thread is here














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值