苹果高级NSOperations示例代码中的竞态条件问题

7

TL:DR

.Completed状态何时设置在NSURLSessionTask上,它如何影响同一任务的completionHandler

是否有方法确保.Completed状态仅在completionHandler执行完成后设置?

问题

在这里关注另一个问题... 在Swift中链接多个异步函数

我被引导到高级NSOperations WWDC Talk示例代码

在将部分代码复制到我的项目后,我发现遇到竞争条件,情况取决于竞争条件如何发挥作用,有时会成功并有时会失败。

我创建的操作几乎与样品代码中的DownloadEarthquakesOperation相同。

它是GroupOperation的子类,并包含一个URLSessionTaskOperation。使用completionHandler创建NSURLSessionTask处理下载的数据。

URLSessionTaskOperation类通过观察其任务的state属性,然后在更改为.Completed时完成操作。

我遇到的问题是,在completionHandler完成处理之前,似乎任务的state已更改为.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
}

这里没有异步代码。

在完成此操作后(相当于示例代码中的GetEarthquakesOperation),此部分操作从实例变量中获取值并将其传递到下一个操作。

问题是有时该值存在,有时为nil。

通过在不同类中记录各种行,我可以看到网络操作在完成处理程序的执行过程中的某个时刻被设置为已完成。有时在值设置之前,有时在值设置之后。

令人困惑的是,我已经尝试在示例应用程序中强制发生这种情况,但无法做到。我尝试了sleep执行处理程序和放入长时间执行循环,但两者似乎都无法解决问题。

有谁能帮助我修复这个竞态条件吗?

1个回答

3

好的,这很奇怪。

http://www.oliverfoggin.com/advanced-nsoperations-nsurlsessiondatatask-vs-nsurlsessiondownloadtask/

NSURLSessionDataTask和NSURLSessionDownloadTask两者在运行完成处理程序并设置完成状态方面有所不同。

下载任务仅在完成处理程序执行完毕后才将自身设置为已完成状态。

数据任务在完成处理程序开始执行后即将自身设置为已完成状态。

这导致了我的项目中出现了竞争条件。我想现在我会切换到使用下载任务。

我也会提交一个radar。


1
我没有解决方法,但是我想说 +1。经过一天的调试,我们得出了与您相同的结论(直到事后才发现您的问题):NSURLSessionDataTask 看起来对 Completed 的定义与 NSURLSessionDownloadTask 不同。这肯定是一个 bug 而不是预期行为。我也会提交一个 Radar。 - Erik Tjernlund
1
在苹果开发者论坛中找到了完全相同的问题,并得到了一位苹果工程师的回答(“我会称之为一个错误”):https://forums.developer.apple.com/thread/36511 - Erik Tjernlund
@ErikTjernlund 哈哈!你不会相信我现在正在iOS会议上坐在Quinn The Eskimo旁边。哈哈!我也会向他指出这一点:D - Fogmeister
1
哇!真是巧合!请转告他,感谢他在论坛上的回答。同时也非常感谢您的帖子,对我们帮助很大。 - Erik Tjernlund

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接