NSOperation - 强制操作动态等待其他操作 [英] NSOperation - Forcing an operation to wait others dynamically

查看:101
本文介绍了NSOperation - 强制操作动态等待其他操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个操作队列,我有以下情况:

I am trying to implement an operation queue and I have the following scenario:

NSOperation A
NSOperation B
NSOperation C
NSOperation D
NSOperationQueue queue

我开始添加 A 队列

执行<期间code> A 我需要从 B 获取一些数据,我无法继续使用 A 直到 B 返回我需要的内容。

During the execution of A I need to get some data from B and I can't continue with A until B returns what I need.

B 也会出现同样的情况,具体取决于 C C 取决于 D

The same situation will occur for B depending on C and for C depending on D.

To管理这个,在每个 NSOperation 我有这个代码:

To manage this, at each NSOperation I have this code:

NSOperation *operation; //This can be A, B, C, D or any other NSOperation

[self setQueuePriority:NSOperationQueuePriorityVeryLow]; //Set the current NSOperation with low priority

[queue addOperation: operation]; //Add the operation that I want to the queue

while(!operation.isFinished && !self.isCancelled){} //I need to wait the operation that I depend before moving on with the current operation

[self setQueuePriority:NSOperationQueuePriorityNormal]; //After the while, the other operation finished so I return my priority to normal and continue

if(self.isCancelled){ //If I get out of the while because the current operation was cancelled I also cancel the other operation.
[operation cancel];          
}

我的问题是,当我有3或4 NSOperations 等待并执行 while(!operacao.isFinished&&!self.isCancelled){} 我的代码只是冻结,因为对我来说很重要的NSOperation不会被执行,即使它具有更高的优先级。

My problem is that when I have something like 3 or 4 NSOperations waiting and executing the while(!operacao.isFinished && !self.isCancelled){} my code just freeze because the NSOperation that is important to me don't get executed, even if it have higher priority.

我尝试了什么


  • 在执行期间添加依赖关系但由于我的NSOperation已经在运行,我似乎没有任何效果。

  • Adding dependency during execution time but since my NSOperation is already running I doesn't seems to have any effect.

我可以做一些 [操作开始] ,而不是将操作添加到队列中。它可以工作,但取消当前的操作也会取消我开始的其他操作吗?

Instead of adding the operation to queue, I can do something [operation start]. It works, but canceling the current operation will also cancel the other operations that I started?

我可以做一些类似的事情(! operacao.isFinished&&!self.isCancelled){[NSThread sleepForTimeInterval:0.001];} 。它有效,但这是正确的方法吗?也许有更好的解决方案。

I can do something like while(!operacao.isFinished && !self.isCancelled){[NSThread sleepForTimeInterval:0.001];}. It works, but is this the correct way? Maybe there is a better solution.

在这种情况下我怎么能保证我想要的操作会运行而其他人会在后台等待?解决这个问题的正确方法是什么?

In this situation how I can guarantee that the operation that I want will run and the others will wait in background? What is the correct way to solve this?

如果有人质疑我为什么在开始我的队列之前没有添加依赖项,因为只有当一个操作需要另一个操作时有些条件是真的。我会知道我是否只在执行期间需要其他操作。

If anyone question me why I don't add the dependency before starting my queue its because an operation will need the other only if some conditions are true. I will know if I need other operation only during execution time.

感谢您的时间。

推荐答案

这里有两个有人为的例子的想法。我只使用了两个操作,但您可以将概念扩展为任意数字和/或根据需要嵌套它们。

Here's two ideas for you with contrived examples. I only used two operations but you could expand the concept to any number and/or nest them as needed.

GCD提供轻量级调度组,允许您明确地命令任务,然后等待完成。在这种情况下,AlphaOperation创建一个组并输入它,然后启动BetaOperation,其 completionBlock 导致该组被留下。当你调用 dispatch_group_wait 时,当前线程会阻塞,直到进入组的次数等于离开它的次数(很像保留计数)。在任何可能长时间运行的任务之后,不要忘记检查 isCancelled 操作状态。

GCD provides lightweight "dispatch groups", which allow you to explicitly order tasks and then wait on their completion. In this case AlphaOperation creates a group and enters it, then starts BetaOperation, whose completionBlock causes the group to be left. When you call dispatch_group_wait, the current thread blocks until the number of times entering the group is equal to the number of times leaving it (a lot like retain count). Don't forget to check the isCancelled state of the operation after any potentially long-running task.

@interface BetaOperation : NSOperation
@end
@implementation BetaOperation
- (void)main
{
    NSLog(@"beta operation finishing");
}
@end

@interface AlphaOperation : NSOperation
@end
@implementation AlphaOperation
- (void)main
{
    dispatch_group_t group = dispatch_group_create();
    dispatch_group_enter(group);

    BetaOperation *betaOperation = [[BetaOperation alloc] init];
    betaOperation.completionBlock = ^{
        dispatch_group_leave(group);
    };

    [betaOperation start];

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    if ([self isCancelled])
        return;

    NSLog(@"alpha operation finishing");
}
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    dispatch_async(dispatch_get_main_queue(), ^{
        AlphaOperation *operation = [[AlphaOperation alloc] init];
        [operation start];
    });

    return YES;
}

@end



示例2:使用本地NSOperationQueue



由于您已经开始工作,另一个选择是创建一个队列作为AlphaOperation的属性,然后添加BetaOperation并调用 waitUntilAllOperationsAreFinished 在队列中。这有一个额外的好处,你可以在取消AlphaOperation时轻松取消队列的操作,只需重写取消方法。

Example 2: Using a local NSOperationQueue

Since you're already with working operations, another option is creating a queue as a property of AlphaOperation, then adding BetaOperation and calling waitUntilAllOperationsAreFinished on the queue. This has an added benefit in that you can easily cancel the queue's operations when AlphaOperation is cancelled, simply by overriding the cancel method.

@interface BetaOperation : NSOperation
@end
@implementation BetaOperation
- (void)main
{
    NSLog(@"beta operation finishing");
}
@end

@interface AlphaOperation : NSOperation
@property (strong) NSOperationQueue *queue;
@end
@implementation AlphaOperation
- (void)main
{
    self.queue = [[NSOperationQueue alloc] init];

    BetaOperation *betaOperation = [[BetaOperation alloc] init];
    [self.queue addOperation:betaOperation];
    [self.queue waitUntilAllOperationsAreFinished];

    if ([self isCancelled])
        return;

    NSLog(@"alpha operation finishing");
}

- (void)cancel
{
    [super cancel];

    [self.queue cancelAllOperations];
}
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    dispatch_async(dispatch_get_main_queue(), ^{
        AlphaOperation *operation = [[AlphaOperation alloc] init];
        [operation start];
    });

    return YES;
}

@end

这篇关于NSOperation - 强制操作动态等待其他操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆