2017-04-24 8 views
6

मैं एक्सडी दस्तावेज़ ऑब्जेक्ट्स में बड़े एक्सएमएल दस्तावेज़ लोड करना चाहता हूं। XDocument.Load(path, loadOptions) का उपयोग कर सरल सिंक्रोनस दृष्टिकोण बहुत अच्छा काम करता है, लेकिन बड़ी फ़ाइलों (विशेष रूप से नेटवर्क स्टोरेज से) लोड करते समय एक जीयूआई संदर्भ में असहज रूप से लंबे समय तक ब्लॉक करता है।लोड एक्सडॉक्यूमेंट असीमित रूप से

मैंने दस्तावेज़ लोडिंग में प्रतिक्रिया को बेहतर बनाने के इरादे से इस एसिंक संस्करण को लिखा, विशेष रूप से नेटवर्क पर फ़ाइलों को लोड करते समय।

public static async Task<XDocument> LoadAsync(String path, LoadOptions loadOptions = LoadOptions.PreserveWhitespace) 
    { 
     String xml; 

     using (var stream = File.OpenText(path)) 
     { 
      xml = await stream.ReadToEndAsync(); 
     } 

     return XDocument.Parse(xml, loadOptions); 
    } 

हालांकि, स्थानीय डिस्क से भरी हुई एक 200 एमबी एक्सएमएल कच्चे फ़ाइल पर, तुल्यकालिक संस्करण कुछ ही सेकंड में पूरा करता है। एसिंक्रोनस संस्करण (32-बिट संदर्भ में चल रहा है) के बजाय एक OutOfMemoryException फेंकता है:

at System.Text.StringBuilder.ToString() 
    at System.IO.StreamReader.<ReadToEndAsyncInternal>d__62.MoveNext() 

मैं कल्पना इस XDocument द्वारा पार्स करने के लिए स्मृति में कच्चे एक्सएमएल पकड़ इस्तेमाल अस्थायी स्ट्रिंग चर के कारण है। संभवतः सिंक्रोनस परिदृश्य में, XDocument.Load() स्रोत फ़ाइल के माध्यम से स्ट्रीम करने में सक्षम है, और पूरी फ़ाइल को पकड़ने के लिए कभी भी एक विशाल स्ट्रिंग बनाने की आवश्यकता नहीं है।

क्या दोनों दुनिया के सर्वश्रेष्ठ प्राप्त करने का कोई तरीका है? पूरी तरह से एसिंक्रोनस I/O के साथ XDocument लोड करें, और बिना किसी अस्थायी स्ट्रिंग को बनाने की आवश्यकता के?

+0

शायद आप का उपयोग करना चाहिए 'XDocument.Load (धारा)'? – DavidG

+0

यह लोड ऑपरेशन को असीमित कैसे बनाएगा? – Hydrargyrum

+0

ठीक है कि स्वयं में नहीं होगा, लेकिन यह आपके यहां मौजूद स्ट्रिंग वेरिएबल को समाप्त करेगा और उम्मीद है कि ओओएम अपवाद। – DavidG

उत्तर

2

सबसे पहले कार्य को असीमित रूप से नहीं चलाया जा रहा है। आपको या तो एसिंक IO कमांड में निर्मित या थ्रेड पूल पर एक कार्य को स्पिन करने की आवश्यकता होगी। उदाहरण

public static async Task<XDocument> LoadAsync 
(String path 
, LoadOptions loadOptions = LoadOptions.PreserveWhitespace 
) 
{ 
    return Task.Run(()=>{ 
    using (var stream = File.OpenText(path)) 
     { 
      return XDocument.Load(stream, loadOptions); 
     } 
    }); 
} 

के लिए और अगर आप पार्स की stream version का उपयोग तो आप एक अस्थायी स्ट्रिंग नहीं मिलता है।

+3

ठीक है। इस सवाल पर मैंने अपनी अंतिम टिप्पणी में बताया है। तो यह एक्सडोक्यूमेंट स्ट्रीम के माध्यम से अपना रास्ता चबाने के रूप में, निश्चित रूप से आवश्यक I/O ड्राइव करने के लिए थ्रेड-पूल थ्रेड का उपयोग करेगा। और यह कि मैं/ओ खुद ही कार्य के कार्यकर्ता धागे को अवरुद्ध कर देगा। ऐसा लगता है कि यह एक वास्तविक XDocument.LoadAsync() कार्यान्वयन की अनुपस्थिति में किया जा सकता है, जो हुड के तहत उचित Async I/O निर्देशों का उपयोग करता है। मुझे स्पष्ट रूप से फ़ाइल को कॉल करने के लिए कोई लाभ नहीं दिख रहा है। ओपनटेक्स्ट हालांकि।साथ ही साथ XDocument.Load (पथ) – Hydrargyrum

+0

पर कॉल करें यदि आप समानांतर में सर्वर पर हजारों एक्सडी दस्तावेज़ पढ़ रहे थे तो आप सच एसिंक IO का उपयोग करने के बजाय थ्रेड पूल से थ्रेड चोरी करने के बारे में चिंतित हो सकते हैं लेकिन क्या यह वास्तव में एक चिंता है ? – bradgonesurfing

+1

शायद नहीं। इसलिए मेरी टिप्पणी है कि यह शायद काफी अच्छा है। मैं वैसे भी ऊपर उठाया और स्वीकार किया – Hydrargyrum

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