2

我有一个应用程序可以一次将图像上传到一堆地方,有点像 Instagram 风格。

它设置有一个围绕一个异步NSOperationQueue运行一堆包装器。NSOperationNSURLConnection

大多数以这种方式开始的问题都以“回调没有被调用,因为调用线程在它们返回之前加入。这不是那种问题。我预期得到我的回调,但我也以某种方式阻止了应用程序当按下主页按钮时从后台开始。我一直认为由于沙盒,这根本无法被阻止,但不知何故我做到了。在操作运行时按下主页按钮将什么都不做,直到它们完成,在哪一点(20-30 秒后)应用程序正确背景。

**NB 这似乎只发生在单核处理器设备上。我只能在我的 iPhone 4 上重现,但不能在我的 4S 或 iPad 3 上重现。*

还是有兴趣?这是我的设置:

self.uploadQueue = [[NSOperationQueue alloc] init];
[self.uploadQueue setMaxConcurrentOperationCount:1];
[self.uploadQueue setSuspended:YES];

稍后,我将操作添加到队列中,然后将其取消挂起以启动。以下是这些NSOperation子类的一些代码:

- (BOOL)isConcurrent { return YES; }
- (BOOL)isExecuting { return self.executing; }
- (BOOL)isFinished { return self.finished; }

- (void)start {
    // Omitted: check for cancel...
    // Omitted: check if setup to run

    [self willChangeValueForKey:@"isExecuting"];
    self.executing = YES;
    [self didChangeValueForKey:@"isExecuting"];

    [self.sharer share];    
    CFRunLoopRun();
}


- (void)completeOperation {
    [self willChangeValueForKey:@"isFinished"];
    [self willChangeValueForKey:@"isExecuting"];
    self.executing = NO;
    self.finished = YES;
    [self didChangeValueForKey:@"isExecuting"];
    [self didChangeValueForKey:@"isFinished"];
    CFRunLoopStop(CFRunLoopGetCurrent());
}

share方法设置一个异步NSURLConnection并像这样触发它:

- (void)share {
    // Omitted: connection setup
    [NSURLConnection sendAsynchronousRequest:postRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *responseData, NSError *error){
        // handle error or success, then call
        [self.currentOperation completeOperation];
    }];

除了我试图解决的副作用之外,代码的工作原理是它完成了它应该做的事情,回调被调用,线程只要需要就保持活动状态,并且操作队列只运行指定的一次操作数。

我尝试了什么?我试过了:

  1. [NSOperationQueue currentQueue]. 这导致异步连接不回调该块。
  2. 将每个 NSOperation 强制到start方法中的主线程上。这并没有解决问题,还导致代码有时无法工作并且 UI 有时会冻结。
  3. 使用可变数组和 GCD 实现我自己的队列以进入正确的调度线程。无法让它工作。
  4. 操作中的同步 NSURLConnections。我并没有真正尝试过,因为这不是我的选择。某些网络框架(例如 Facebook iOS SDK)没有同步选项。

在按下主页按钮之后,但在操作完成之前暂停执行不会产生任何有趣的结果。主线程上似乎没有任何东西在等待锁定或执行完成。

主题 1线程 2

我把它设置成一个完整的笨蛋吗?这里发生了什么,我该如何解决?

4

1 回答 1

0

编辑:

原来所有这些网络的东西都是一个红鲱鱼。这是一些循环的 CAAnimations 以某种方式阻止返回跳板。

原始猜测:

我的猜测:你不应该调用CFRunLoopRun你的 start 方法;并发操作的 start 方法预计在操作完成之前返回并稍后完成。您可能持有系统需要调度其他任务的一些 GCD 锁(线程?)。

如果你需要通过 独占一个线程CFRunLoopRun,你应该启动你自己的线程start然后返回。不过,我认为这会更容易,只是不使用 NSOperation 并从主线程启动您的(已经异步的)url 连接,在每个完成时保留一系列要共享的东西。

实际上,我认为问题在于CFRunLoopStop(CFRunLoopGetCurrent()):您正在主线程上运行它,所以您正在停止主运行循环!

于 2012-06-29T01:26:33.873 回答