मैं एक सी #, यूडब्ल्यूपी 10 समाधान विकसित कर रहा हूं जो एक तेज, निरंतर पढ़ने/लिखने के लूप का उपयोग कर नेटवर्क डिवाइस के साथ संचार करता है। एपीआई द्वारा प्रस्तावित स्ट्रीमस्केट बहुत अच्छा काम करता था, जब तक मुझे एहसास हुआ कि स्मृति मेमोरी थी: सैकड़ों मिनट के क्रम में, ढेर में Task<uint32>
का संचय होता है।एक लूप में StreamSocket का उपयोग क्यों स्मृति रिसाव का कारण बनता है?
मैं एक async Task
अंदर एक सादे पुराने while (true)
पाश, या एक आत्म पोस्टिंग TPL Dataflow साथ ActionBlock<T>
(प्रति this answer के रूप में), परिणाम का उपयोग कर एक ही है का उपयोग करें।
मैं आगे समस्या को अलग करने की अगर मैं सॉकेट से पढ़ने को खत्म करने और लेखन पर ध्यान केंद्रित करने में सक्षम हूँ: मैं DataWriter.StoreAsync
दृष्टिकोण या अधिक प्रत्यक्ष StreamSocket.OutputStream.WriteAsync(IBuffer buffer)
का उपयोग हैं, समस्या बनी हुई है। इसके अलावा, .AsTask()
को जोड़ने से कोई फर्क नहीं पड़ता।
कचरा कलेक्टर चलाने पर भी, इन Task<uint32>
को कभी भी ढेर से हटाया नहीं जाता है। ये सभी कार्य पूर्ण हैं (RanToCompletion
), इसमें कोई त्रुटि या कोई अन्य संपत्ति मान नहीं है जो "पुनः दावा करने के लिए तैयार नहीं है" इंगित करेगा।
this page पर मेरी समस्या का संकेत मिलता है (प्रबंधित से अप्रबंधित दुनिया से चलने वाला एक बाइट सरणी स्मृति की रिहाई को रोकता है), लेकिन निर्धारित समाधान बहुत स्पष्ट लगता है: इस के आसपास एकमात्र तरीका सभी को लिखना है सी ++/सीएक्स में संचार तर्क। मुझे उम्मीद है कि यह सच नहीं है; निश्चित रूप से अन्य सी # डेवलपर्स ने मेमोरी लीक के बिना लगातार उच्च गति नेटवर्क संचारों को सफलतापूर्वक महसूस किया है। और निश्चित रूप से माइक्रोसॉफ्ट मेमोरी लीक सी ++/CX में
संपादित
का अनुरोध किया, कुछ नमूना कोड के रूप में बिना कोई API कि केवल काम करता है रिलीज नहीं होगी। मेरे अपने कोड में बहुत सारी परतें हैं, लेकिन this Microsoft sample के साथ एक बहुत ही सरल उदाहरण देखा जा सकता है। मैंने समस्या को उजागर करने के लिए लूप में 1000 बार भेजने के लिए एक सरल संशोधन किया।
public sealed partial class Scenario3 : Page
{
// some code omitted
private async void SendHello_Click(object sender, RoutedEventArgs e)
{
// some code omitted
StreamSocket socket = //get global object; socket is already connected
DataWriter writer = new DataWriter(socket.OutputStream);
for (int i = 0; i < 1000; i++)
{
string stringToSend = "Hello";
writer.WriteUInt32(writer.MeasureString(stringToSend));
writer.WriteString(stringToSend);
await writer.StoreAsync();
}
}
}
एप्लिकेशन को शुरू करने और सॉकेट जोड़ने पर, वहाँ Task<UInt32>
ढेर पर की केवल उदाहरण है: यह प्रासंगिक कोड है। "SendHello" बटन पर क्लिक करने के बाद, 86 उदाहरण हैं। इसे दूसरी बार दबाकर: 12 9 उदाहरण।
# संपादित 2 मेरे एप्लिकेशन चलाने के बाद (तंग पाश भेजने के साथ/प्राप्त) 3 घंटे के लिए, मैं देख सकता है कि वहाँ निश्चित रूप से एक समस्या है: 0.5 लाख टास्क उदाहरणों, जो GC'd कभी नहीं मिलता है, और ऐप की प्रक्रिया मेमोरी प्रारंभिक 46 एमबी से 105 एमबी तक बढ़ी। जाहिर है यह ऐप अनिश्चितता से नहीं चल सकता है। हालांकि ... यह केवल डीबग मोड में चलने पर लागू होता है। अगर मैं रिलीज मोड में अपना ऐप संकलित करता हूं, इसे तैनात करता हूं और इसे चलाता हूं, तो कोई मेमोरी समस्या नहीं होती है। मैं इसे पूरी रात चल सकता हूं और यह स्पष्ट है कि स्मृति ठीक से प्रबंधित की जा रही है। केस बंद हुआ।
समस्या प्रदर्शित करने वाले कोड को पोस्ट करें – alexm
@alexm, कृपया पोस्ट कोड देखें। Thx – BCA
@BCA - ईवेंट हैंडलर में वैश्विक ऑब्जेक्ट का संदर्भ दे रहे समय पर यह कचरा पृष्ठ कैसे एकत्र कर सकता है? –