我正試圖在我的腦海中構建一個基本上是併發下載管理器的Cocoa應用程序的最佳方式。應用程序會與之對話的一個服務器,用戶列出一大堆要下拉的內容,然後應用程序處理該列表。 (它不使用HTTP或FTP,所以我不能使用URL加載系統;我將通過套接字連接進行通信。)Cocoa中的併發網絡客戶端
這基本上是經典的生產者 - 消費者模式。訣竅是消費者的數量是固定的,而且是持久的。服務器對可以打開的同時連接數設置了嚴格限制(通常至少爲兩個),並且打開新連接的開銷很大,因此在理想的情況下,應用程序的整個生命週期內都會打開相同的N個連接。
解決這個問題的一種方法可能是創建N個線程,每個線程將「擁有」一個連接,然後等待請求隊列,阻止它爲空。由於連接數量永遠不會很大,所以在實際系統開銷方面這不是不合理的。但從概念上來說,Cocoa似乎必須提供更優雅的解決方案。
看來我可以使用NSOperationQueue
,並調用setMaxConcurrentOperationCount:
與連接數。然後我只是把下載請求扔進那個隊列。但在這種情況下,我不確定如何自己管理連接。 (只要把它們放在一個堆棧上,並且依靠隊列來確保我不會超出/低於運行?在dispatch semaphore連同堆棧一起投擲?)
現在我們處於勇敢的新世界Grand Central Dispatch,這是否打開了解決這個問題的其他方法?乍一看,它看起來並不像它,因爲GCD的動態擴展併發性的能力(並在蘋果的Changing Producer-Consumer Implementations建議中提到)實際上並不能幫助我。但我只是抓了一下閱讀的表面。
編輯:
在如此重要的情況:是的,我打算使用異步/非阻塞套接字的API做的與服務器的實際通信。所以I/O本身不一定要在它自己的線程上。我只關心排隊工作的機制,並且(安全地)將它放到連接處,因爲它們變得可用。
該應用程序幾乎肯定不受CPU限制。下載完成後會有一些解碼任務,但我可以將它們發送給GCD進行處理。我主要關注的問題是1)保持UI的響應,2)避免任何競爭條件下工作。如果I/O回調函數全部在主線程上運行,這通常可以解決(2),但是我想知道它是以(1)爲代價的。據推測,大部分工作只是將東西添加到緩衝區中,而且應該很快。 – 2009-09-30 00:05:48