gpt4 book ai didi

ios - NSOperation 死锁并阻塞 NSOperationQueue

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:06:32 26 4
gpt4 key购买 nike

我使用 NSOperation 的子类通过亚马逊的 iOS SDK (v1.3.2) 将大文件上传到 AWS S3。这一切工作正常,但一些 Beta 测试人员遇到死锁 (iOS 5.1.1)。结果是调度操作的 NSOperationQueue 被阻塞,因为一次只允许运行一个操作。问题是我无法重现该问题,而 Beta 测试人员每次都会遇到此问题。

由于 AWS iOS SDK 的工作方式,操作相当复杂。但是,据我所知,根据我的测试,该问题与 AWS iOS SDK 无关。该操作的主要方法粘贴在下面。操作的main方法的思路是基于this Stack Overflow question .

- (void)main {
// Operation Should Terminate
_operationShouldTerminate = NO;

// Notify Delegate
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate operation:self isPreparingUploadWithUuid:self.uuid];
});

// Increment Network Activity Count
[self incrementNetworkActivityCount];

// Verify S3 Credentials
[self verifyS3Credentials];

while (!_operationShouldTerminate) {
if ([self isCancelled]) {
_operationShouldTerminate = YES;

} else {
// Create Run Loop
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}

// Decrement Network Activity Count
[self decrementNetworkActivityCount];

NSLog(@"Operation Will Terminate");
}

完成分段上传的方法将 bool 值 _operationShouldTerminate 设置为 YES 以终止操作。该方法看起来像这样。

- (void)finalizeMultipartUpload {
// Notify Delegate
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate operation:self didFinishUploadingUploadWithUuid:self.uuid];
});

// Operation Should Terminate
_operationShouldTerminate = YES;

NSLog(@"Finalize Multipart Upload");
}

最终的日志语句被打印到控制台,但是 main 方法中的 while 循环似乎并没有退出,因为操作的 main 方法中的最终日志语句没有被打印到控制台。结果,调度操作的操作队列被阻塞,任何调度的操作都不会因此执行。

操作的 isFinished 方法仅返回 _operationShouldTerminate,如下所示。

- (BOOL)isFinished {
return _operationShouldTerminate;
}

奇怪的是 while 循环没有退出,更奇怪的是它没有发生在我自己的任何测试设备(iPhone 3GS、iPad 1 和 iPad 3)上。非常感谢任何帮助或指点。

最佳答案

事实证明,问题的解决方案既复杂又简单。我错误地认为操作的方法和委托(delegate)回调是在同一个线程上执行的,即调用操作的 main 方法的线程。情况并非总是如此。

即使在我的测试和我的设备 (iPhone 3GS) 上都是如此,这也是我自己没有遇到这个问题的原因。但是,我的 beta 测试人员使用的是具有多核处理器的设备 (iPhone 4/4S),这导致某些代码在与调用操作的 main 方法的线程不同的线程上执行。

这样做的结果是 _operationShouldTerminate 在错误线程的 finalizeMultipartUpload 方法中被修改。这反过来意味着 main 方法的 while 循环没有正确退出,导致操作死锁。

简而言之,解决方案是在调用 main 方法的同一线程上更新 _operationShouldTerminate。这将正确退出 while 循环并退出操作。

关于ios - NSOperation 死锁并阻塞 NSOperationQueue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12369607/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com