एसिंक सॉकेट को प्रभावी रूप से कार्यान्वित करने के लिए प्रत्येक सॉकेट को 1 सॉकेटएसिंसेन्ट आर्ट्स से अधिक की आवश्यकता होगी। प्रत्येक SocketAsyncEventArgs में बाइट [] बफर के साथ एक समस्या भी है। संक्षेप में, जब भी प्रबंधित - देशी संक्रमण होता है (भेजना/प्राप्त करना) बाइट बफर को पिन किया जाएगा। यदि आप आवश्यकतानुसार सॉकेटएसिंसेन्ट आर्ट्स और बाइट बफर आवंटित करते हैं तो आप विखंडन के कारण कई ग्राहकों के साथ आउटऑफमेमरी अपवादों में भाग ले सकते हैं और जीसी की निष्क्रियता को संक्रमित करने की अक्षमता के कारण।
इसे संभालने का सबसे अच्छा तरीका सॉकेटबफरपूल क्लास बनाना है जो एप्लिकेशन को पहली बार शुरू होने पर बड़ी संख्या में बाइट्स और सॉकेटएसिंसेन्ट आर्ट्स आवंटित करेगा, इस तरह पिन की गई मेमोरी संगत होगी। फिर आवश्यकतानुसार पूल से बफर का पुन: उपयोग करें।
प्रैक्टिस में मुझे संसाधनों के वितरण को प्रबंधित करने के लिए सॉकेटएसिंसेन्ट आर्ट्स और सॉकेटबफरपूल क्लास के चारों ओर एक रैपर वर्ग बनाने के लिए सबसे अच्छा मिला है।
private void BeginReceive(Socket socket)
{
Contract.Requires(socket != null, "socket");
SocketEventArgs e = SocketBufferPool.Instance.Alloc();
e.Socket = socket;
e.Completed += new EventHandler<SocketEventArgs>(this.HandleIOCompleted);
if (!socket.ReceiveAsync(e.AsyncEventArgs)) {
this.HandleIOCompleted(null, e);
}
}
यहाँ और HandleIOCompleted विधि है::
उदाहरण के लिए, यहाँ एक BeginReceive विधि के लिए कोड है
private void HandleIOCompleted(object sender, SocketEventArgs e)
{
e.Completed -= this.HandleIOCompleted;
bool closed = false;
lock (this.sequenceLock) {
e.SequenceNumber = this.sequenceNumber++;
}
switch (e.LastOperation) {
case SocketAsyncOperation.Send:
case SocketAsyncOperation.SendPackets:
case SocketAsyncOperation.SendTo:
if (e.SocketError == SocketError.Success) {
this.OnDataSent(e);
}
break;
case SocketAsyncOperation.Receive:
case SocketAsyncOperation.ReceiveFrom:
case SocketAsyncOperation.ReceiveMessageFrom:
if ((e.BytesTransferred > 0) && (e.SocketError == SocketError.Success)) {
this.BeginReceive(e.Socket);
if (this.ReceiveTimeout > 0) {
this.SetReceiveTimeout(e.Socket);
}
} else {
closed = true;
}
if (e.SocketError == SocketError.Success) {
this.OnDataReceived(e);
}
break;
case SocketAsyncOperation.Disconnect:
closed = true;
break;
case SocketAsyncOperation.Accept:
case SocketAsyncOperation.Connect:
case SocketAsyncOperation.None:
break;
}
if (closed) {
this.HandleSocketClosed(e.Socket);
}
SocketBufferPool.Instance.Free(e);
}
ऊपर कोड एक TcpSocket वर्ग कि बढ़ा देंगे में निहित है DataReceived & डेटासेंट घटनाओं। नोटिस करने के लिए एक बात यह है कि सॉकेटएसिंकऑपरेशन। रिसीव मैसेज फ्रॉम: ब्लॉक; अगर सॉकेट में कोई त्रुटि नहीं है तो यह तुरंत एक और BeginReceive() शुरू करता है जो पूल से एक और सॉकेटइवर्ट्स आवंटित करेगा।
एक और महत्वपूर्ण नोट है सॉकेटइवेंट आर्ट्स सीक्वेंस नम्बर संपत्ति हैंडलऑकंपलेट विधि में सेट है। यद्यपि async अनुरोध कतारबद्ध क्रम में पूरा हो जाएंगे, फिर भी आप अन्य थ्रेड रेस स्थितियों के अधीन हैं। चूंकि डेटा DataReceived ईवेंट को बढ़ाने से पहले BeginReceive को कॉल करता है, इसलिए संभावना है कि प्रारंभिक आईओसीपी सर्विसिंग थ्रेड रीसीसीव को कॉल करने के बाद अवरुद्ध हो जाएगी, लेकिन घटना को नाराज करने से पहले, जबकि दूसरा एसिंक एक नए थ्रेड पर पूरा हो जाता है जो पहले डेटा रिसीव किए गए ईवेंट को बढ़ाता है। यद्यपि यह एक दुर्लभ बढ़त वाला मामला है, लेकिन यह हो सकता है कि अनुक्रमांक संपत्ति उपभोग करने वाले ऐप को यह सुनिश्चित करने की क्षमता प्रदान करती है कि सही क्रम में डेटा संसाधित हो।
एसिंक भेजता है एक अन्य क्षेत्र एसिंक भेजता है। अक्सर, async भेजने के अनुरोध सिंक्रनाइज़ हो जाएंगे (अगर कॉल सिंक्रनाइज़ेशन पूर्ण हो तो SendAsync झूठी वापसी करेगा) और प्रदर्शन को गंभीर रूप से खराब कर सकता है। एक आईओसीपी पर वापस आने वाले एसिंक कॉल का अतिरिक्त ओवरहेड अभ्यास में सिंक्रोनस कॉल का उपयोग करने से भी खराब प्रदर्शन कर सकता है। Async कॉल को दो कर्नेल कॉल और एक ढेर आवंटन की आवश्यकता होती है जबकि सिंक्रोनस कॉल स्टैक पर होता है।
आशा इस मदद करता है, विधेयक