2016-09-22 73 views
0

我有一個用例,我需要使用NSURLSession下載許多文件。在內部nsoperation中使用Runloop進行異步任務

爲了保持sessiontasks從超時,我需要將它們放置在一個操作隊列和限制併發下載量,使他們不捱餓。

我的想法是,我將在任務的簡歷加載到的NSOperation,並將它們加載到nsoperationqueue,這將限制併發activitiy的數量。

的問題是,當我打電話[任務簡歷]代碼將退出和的NSOperation將考慮即使我等待文件完成下載本身完成。

這是一些代碼。

NSURLSessionDownloadTask *task = [session downloadTaskWithRequest: request 
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { 

    //move the file to a permanent location 

    CFRunLoopStop(CFRunLoopGetCurrent()); 
} 
//I have instantiated a class global NSOperation queue. 
[imageDownloadQueue addOperationWithBlock:^void() { 
    [task resume]; 
    CFRunLoopRun(); 
}]; 

我在等待回調時如何保持nsoperation線程存活?我也嘗試使用nsrunloop並添加一個端口到NSMachPort。這似乎沒有幫助。

而且,設置HttpMaximumConnectionsPerHost上NSURLSession沒有幫助,因爲當我恢復任務的超時定時器啓動。這意味着我會得到比以前更多的超時。

+1

請參閱https://developer.apple.com/videos/play/wwdc2015/226/(WWDC 2015高級NSOperations),其中廣泛討論了這些類型的問題。一年後,我向戴夫德隆詢問了這些模式,看看他是否仍然認爲自己在工作。他說這仍然是非常成功的。 –

+0

這是一個很好的視頻,但我沒有時間重寫模式。這是比這涉及更多的代碼。我只是想讓線程保持活躍狀態​​,並且需要回調來移除自身。 – mac10688

+0

這是異步NSOperations的用途。你做一個自定義的'NSOperation',爲'isAsynchronous'返回'true',並覆蓋'start()'而不是'main()'。您必須在適當的時間手動設置「isExecuting」和「isFinished」(即您的操作完成時)。你不希望「線程保持活着」。您希望操作在正確的時間標記自己完成。這就是異步操作的工作原理。它只是意味着你手動完成而不是「當main()'返回時」。「 –

回答

1

不幸的是,我沒有時間做適當的修復,我需要儘快修復超時問題。我發現了一些有用的東西。

//I have instantiated a class global NSOperation queue. 
[imageDownloadQueue addOperationWithBlock:^void() { 
    [task resume]; 
    while(task.state == NSURLSessionTaskStateRunning) 
    { 
     [NSThread sleepForTimeInterval:.1]; 
    } 
    }]; 

由於NSOperation在後臺線程上工作,我可以在任務運行時睡眠該線程。這樣可以防止線程死亡,但是任務將在它自己的線程上運行並且不會被阻止。