2009-07-28 4 views
9

यह स्टैक ओवरव्लो प्रश्न Managing multiple asynchronous NSURLConnection connectionsकोको: समान प्रतिनिधि कार्यों का उपयोग करके एकाधिक एसिंक्रोनस NSURLConnections के लिए आवश्यक चेक?

के संदर्भ में है, मेरे पास एक ही समय में एकाधिक असीमित HTTP अनुरोध किए जा रहे हैं। ये सभी एक ही NSURLConnection प्रतिनिधि कार्यों का उपयोग करते हैं। (प्राप्तडेटा ऑब्जेक्ट उपरोक्त दूसरे प्रश्न में निर्दिष्ट प्रत्येक कनेक्शन के लिए अलग है। प्रतिनिधि में, मैं प्राप्त दिनांक वस्तु को पार्स करता हूं, और उन पार्स किए गए तारों पर अतिरिक्त संचालन करता हूं)

सबकुछ मेरे लिए अब तक ठीक काम करता है, लेकिन मैं मुझे यकीन नहीं है कि मुझे सही "बहुप्रचारित" व्यवहार सुनिश्चित करने के लिए कुछ भी करने की ज़रूरत है।

  • क्या यह संभव है कि दो से अधिक कनेक्शन एक ही समय में प्रतिनिधि का उपयोग करेंगे? (मुझे हाँ लगता है)
  • यदि हां, तो इसका समाधान कैसे किया जाता है? (क्या कोको स्वचालित रूप से ऐसा करता है?)
  • क्या मुझे यह सुनिश्चित करने के लिए अतिरिक्त जांच की आवश्यकता है कि प्रत्येक अनुरोध को "सही" से संभाला जाए?

उत्तर

13

मान लें कि आप एक ही थ्रेड पर सभी (एसिंक्रोनस) कनेक्शन लॉन्च कर रहे हैं, तो प्रतिनिधि संदेश सभी उस थ्रेड के रन लूप में पोस्ट हो जाएंगे। इसलिए प्रतिनिधि को केवल एक संदेश को एक साथ संभालने में सक्षम होना चाहिए; रन लूप एक समय में एक संदेश बंद कर देगा। इसका मतलब है कि प्रतिनिधि संदेश का आदेश अज्ञात है और अगला संदेश किसी भी कनेक्शन ऑब्जेक्ट से आ सकता है, आपके प्रतिनिधि तरीकों का कोई समवर्ती निष्पादन नहीं होगा।

हालांकि, आप वास्तव में एपीआई की एसिंक्रोनस प्रकृति का उपयोग करने के बजाय, एकाधिक धागे में एक ही प्रतिनिधि वस्तु का उपयोग करने की कोशिश कर रहे थे, तो आप समवर्ती प्रतिनिधि विधियों से निपटने की आवश्यकता है।

0

हां यह एकाधिक कनेक्शन होना संभव है। अधिसूचना ऑब्जेक्ट में NSURLConnection पर एक पॉइंटर होता है जो अधिसूचना को ट्रिगर करता है।

आंतरिक रूप से मुझे लगता है कि NSURLConnection सॉकेट को सुनता है और जब डेटा तैयार होता है तो ऐसा कुछ करता है।

[your_delegate 
    performSelectorOnMainThread:@selector(connectionCallback:) 
    withObject:self 
    waitUntilDone:NO]; 

ताकि आप इसे बहु होने के बारे में चिंता करने की ज़रूरत नहीं है, NSURLConnection इस का ख्याल रखना होगा। सादगी के लिए मैंने स्वयं को लिखा है, वास्तविक दुनिया में NSNotification ऑब्जेक्ट दिया गया है।

आपको मल्टीथ्रेडिंग से संबंधित कोई भी चेक नहीं करना चाहिए।

19

मैंने यूजर के साथ खेलने के बावजूद डेटा लाने के लिए कई थ्रेडों में एसिंक्रोनस कनेक्शन को लागू करने के लिए थ्री 20 लाइब्रेरी को बढ़ाया। सीएफनेटवर्क ढांचे के भीतर पाए गए यादृच्छिक मेमोरी लीक का पीछा करने के कई घंटों बाद मैंने अंततः इस मुद्दे को रूट किया। मैं कभी-कभी प्रतिक्रियाओं और डेटा का ट्रैक खो रहा था।

एकाधिक थ्रेड द्वारा उपयोग की जाने वाली किसी भी डेटा संरचना को उचित लॉक द्वारा संरक्षित किया जाना चाहिए। यदि आप पारस्परिक रूप से अनन्य तरीके से साझा डेटा संरचनाओं तक पहुंचने के लिए ताले का उपयोग नहीं कर रहे हैं तो आप थ्रेड सुरक्षित नहीं हैं। ऐप्पल के Threading Programming Guide के "Using Locks" अनुभाग देखें।

सबसे अच्छा समाधान NSURLConnection को उपclass करना है और इसके संबंधित प्रतिक्रिया और प्रतिक्रिया डेटा को संग्रहीत करने के लिए इंस्टेंस चर जोड़ें।प्रत्येक कनेक्शन प्रतिनिधि विधि में आप NSRLConnection को अपने उप-वर्ग में डालें और उन आवृत्ति चरों तक पहुंचें। यह पारस्परिक रूप से अनन्य होने की गारंटी है क्योंकि प्रत्येक कनेक्शन को अपनी प्रतिक्रिया और डेटा के साथ बंडल किया जाएगा। मैं अत्यधिक कोशिश कर रहा हूं क्योंकि यह सबसे साफ समाधान है। मेरे कार्यान्वयन से कोड यहां दिया गया है:

@interface TTURLConnection : NSURLConnection { 
NSHTTPURLResponse* _response; 
NSMutableData* _responseData; 
} 

@property(nonatomic,retain) NSHTTPURLResponse* response; 
@property(nonatomic,retain) NSMutableData* responseData; 

@end 

@implementation TTURLConnection 

@synthesize response = _response, responseData = _responseData; 

- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate { 
NSAssert(self != nil, @"self is nil!"); 

// Initialize the ivars before initializing with the request 
    // because the connection is asynchronous and may start 
    // calling the delegates before we even return from this 
    // function. 

self.response = nil; 
self.responseData = nil; 

self = [super initWithRequest:request delegate:delegate]; 
return self; 
} 

- (void)dealloc { 
[self.response release]; 
[self.responseData release]; 

[super dealloc]; 
} 

@end 

///////////////////////////////////////////////////////////////// 
////// NSURLConnectionDelegate 

- (void)connection:(NSURLConnection*)connection 
didReceiveResponse:(NSHTTPURLResponse*)response { 
TTURLConnection* ttConnection = (TTURLConnection*)connection; 
ttConnection.response = response; 
ttConnection.responseData = [NSMutableData 
           dataWithCapacity:contentLength]; 
} 

- (void)connection:(NSURLConnection*)connection 
    didReceiveData:(NSData*)data { 
TTURLConnection* ttConnection = (TTURLConnection*)connection; 
[ttConnection.responseData appendData:data]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 
TTURLConnection* ttConnection = (TTURLConnection*)connection; 

    if (ttConnection.response.statusCode == 200) { 
     // Connection success 
    } 
} 

- (void)connection:(NSURLConnection *)connection 
    didFailWithError:(NSError *)error { 
    TTURLConnection* ttConnection = (TTURLConnection*)connection; 
    // Handle the error 
} 
+0

आपके सुझाव के लिए धन्यवाद, मेरा मानना ​​है कि यह इसे संभालने का सबसे प्रभावी तरीका है। मुझे आश्चर्य है कि इतने सालों के बाद, ऐप्पल ने अभी भी एनएसआरयूटीएबलडेटा * को NSURLConnection में नहीं छोड़ा है। मुझे कोई कारण नहीं दिख रहा है कि उन्हें क्यों नहीं करना चाहिए। यह एक मानक ऑपरेशन है आप नहीं कहेंगे? – taylorcressy

संबंधित मुद्दे