Apple 的 Advanced NSOperations 示例代码中的竞争条件
Race condition in Apple's sample code for Advanced NSOperations
TL:DR
什么时候在 NSURLSessionTask
上设置 .Completed
状态,它如何 depend/affect 同一任务的 completionHandler
?
有没有办法确保 .Completed
状态仅在 completionHandler
执行完毕后设置?
问题
在此处关注另一个问题...
我被指向了高级 NSOperations 的方向 WWDC Talk and Sample Code。
将部分代码复制到我自己的项目中后,我发现我似乎遇到了一个竞争条件,它有时会工作,有时会失败,具体取决于竞争条件的执行方式。
我创建的操作几乎是示例代码中 DownloadEarthquakesOperation
的副本。
它是 GroupOperation
的子class,并包含一个 URLSessionTaskOperation
。 NSURLSessionTask
是使用处理下载数据的 completionHandler
创建的。
classURLSessionTaskOperation
的工作原理是观察其任务的state
属性,然后在更改为.Completed
时完成操作。
我遇到的问题是任务的 state
似乎在 completionHandler
完成处理之前更改为 .Completed
。
我的完成处理程序是这样的...
// this is a direct copy of the sample code just using data task
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
self.downloadFinished(data, response: response as? NSHTTPURLResponse, error: error)
}
它调用的函数(伪代码)是这样的...(我目前无法访问确切的代码)。
func downloadFinished(data: NSData?, response: NSHTTPURLResponse?, error, NSError?) {
// if the error is not nil then finish operation with error
// if the response status code is not correct then finish with error
// try to convert the data to a JSON object using NSJSONSerialization
// finish with error if conversion failed
// get a single Int value out of the JSON object
// store the single Int value in an instance variable
}
这里没有异步代码。
this完成部分操作后(相当于示例代码中的GetEarthquakesOperation
)从实例变量中获取值并传递给下一个操作。
问题是这个值有时存在有时为零。
通过注销不同 classes 中的各个行,我可以看到网络操作在完成处理程序执行的某个时刻被设置为已完成。有时在设置值之前,有时在设置值之后。
令人困惑的是,我曾尝试在示例应用程序中强制执行此操作,但我做不到。我试过 sleep
完成处理程序,我试过放入一个很长的执行时间循环,但它们似乎都不起作用。
任何人都可以帮助我解决这个竞争条件。
好吧,这很奇怪。
http://www.oliverfoggin.com/advanced-nsoperations-nsurlsessiondatatask-vs-nsurlsessiondownloadtask/
NSURLSessionDataTask 和 NSURLSessionDownloadTask 都是 运行 它们的完成处理程序并以不同的方式设置它们的完成状态。
下载任务仅在完成处理程序完成执行后才将自身设置为已完成。
完成处理程序开始执行后,数据任务将自身设置为已完成。
这导致了我自己项目中的竞争条件。我想我暂时改用下载任务。
我也会提交雷达。
TL:DR
什么时候在 NSURLSessionTask
上设置 .Completed
状态,它如何 depend/affect 同一任务的 completionHandler
?
有没有办法确保 .Completed
状态仅在 completionHandler
执行完毕后设置?
问题
在此处关注另一个问题...
我被指向了高级 NSOperations 的方向 WWDC Talk and Sample Code。
将部分代码复制到我自己的项目中后,我发现我似乎遇到了一个竞争条件,它有时会工作,有时会失败,具体取决于竞争条件的执行方式。
我创建的操作几乎是示例代码中 DownloadEarthquakesOperation
的副本。
它是 GroupOperation
的子class,并包含一个 URLSessionTaskOperation
。 NSURLSessionTask
是使用处理下载数据的 completionHandler
创建的。
classURLSessionTaskOperation
的工作原理是观察其任务的state
属性,然后在更改为.Completed
时完成操作。
我遇到的问题是任务的 state
似乎在 completionHandler
完成处理之前更改为 .Completed
。
我的完成处理程序是这样的...
// this is a direct copy of the sample code just using data task
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
self.downloadFinished(data, response: response as? NSHTTPURLResponse, error: error)
}
它调用的函数(伪代码)是这样的...(我目前无法访问确切的代码)。
func downloadFinished(data: NSData?, response: NSHTTPURLResponse?, error, NSError?) {
// if the error is not nil then finish operation with error
// if the response status code is not correct then finish with error
// try to convert the data to a JSON object using NSJSONSerialization
// finish with error if conversion failed
// get a single Int value out of the JSON object
// store the single Int value in an instance variable
}
这里没有异步代码。
this完成部分操作后(相当于示例代码中的GetEarthquakesOperation
)从实例变量中获取值并传递给下一个操作。
问题是这个值有时存在有时为零。
通过注销不同 classes 中的各个行,我可以看到网络操作在完成处理程序执行的某个时刻被设置为已完成。有时在设置值之前,有时在设置值之后。
令人困惑的是,我曾尝试在示例应用程序中强制执行此操作,但我做不到。我试过 sleep
完成处理程序,我试过放入一个很长的执行时间循环,但它们似乎都不起作用。
任何人都可以帮助我解决这个竞争条件。
好吧,这很奇怪。
http://www.oliverfoggin.com/advanced-nsoperations-nsurlsessiondatatask-vs-nsurlsessiondownloadtask/
NSURLSessionDataTask 和 NSURLSessionDownloadTask 都是 运行 它们的完成处理程序并以不同的方式设置它们的完成状态。
下载任务仅在完成处理程序完成执行后才将自身设置为已完成。
完成处理程序开始执行后,数据任务将自身设置为已完成。
这导致了我自己项目中的竞争条件。我想我暂时改用下载任务。
我也会提交雷达。