OutOfMemoryException загрузка xml документа winmo 6.1 - PullRequest
1 голос
/ 24 сентября 2010

Я использую c # на устройстве Windows Mobile 6.1. компактный каркас 3.5. Я получаю OutofMemoryException при загрузке в большой строке XML. Трубка имеет ограниченную память, но ее должно быть более чем достаточно для обработки размера строки xml. Строка xml содержит содержимое base64 файла размером 2 МБ. Код будет работать, если строка xml содержит файлы размером до 1,8 МБ.
Я полностью озадачен тем, что делать. Не уверен, как изменить какие-либо настройки памяти.
Я включил сокращенную копию кода ниже. Любая помощь приветствуется.

 Stream newStream = myRequest.GetRequestStream();
                // Send the data.
                newStream.Write(data, 0, data.Length);
                //close the write stream 
                newStream.Close();
                // Get the response. 
                HttpWebResponse response = (HttpWebResponse)myRequest.GetResponse();
                // Get the stream containing content returned by the server.
                Stream dataStream = response.GetResponseStream();
                //Process the return
                //Set the buffer
                byte[] server_response_buffer = new byte[8192];
                int response_count = -1;

                string tempString = null;

                StringBuilder response_sb = new StringBuilder();
                //Loop through the stream until it is all written
                do
                {
                    // Read content into a buffer
                    response_count = dataStream.Read(server_response_buffer, 0, server_response_buffer.Length);
                    // Translate from bytes to ASCII text
                    tempString = Encoding.ASCII.GetString(server_response_buffer, 0, response_count);
                    // Write content to a file from buffer
                    response_sb.Append(tempString);
                }
                while (response_count != 0);
                responseFromServer = response_sb.ToString();
                // Cleanup the streams and the response.
                dataStream.Close();
                response.Close();
            }
            catch {
                MessageBox.Show("There was an error with the communication.");
                comm_error = true;
            }
              if(comm_error == false){
            //Load the xml file into an XML object

                  XmlDocument xdoc = new XmlDocument();
                  xdoc.LoadXml(responseFromServer);
              }

Ошибка возникает в строке xdoc.LoadXML. Я попытался записать поток в файл, а затем загрузить файл непосредственно в xmldocument, но это было не лучше. Полностью озадачен на этом этапе.

Ответы [ 3 ]

4 голосов
/ 24 сентября 2010

Я бы порекомендовал вам использовать класс XmlTextReader вместо класса XmlDocument. Я не уверен, каковы ваши требования для чтения xml, но XmlDocument требует очень много памяти, так как создает множество объектов и пытается загрузить всю строку xml. Класс XmlTextReader, с другой стороны, просто просматривает xml, когда вы читаете из него.

Если у вас есть строка, это означает, что вы должны сделать что-то вроде следующего:

        String xml = "<someXml />";
        using(StringReader textReader = new StringReader(xml)) {
            using(XmlTextReader xmlReader = new XmlTextReader(textReader)) {
                xmlReader.MoveToContent();
                xmlReader.Read();
                // the reader is now pointed at the first element in the document...
            }
        }
0 голосов
/ 24 сентября 2010

Я не уверен, почему вы читаете xml так, как вы, но это может быть очень неэффективно для памяти.Если сборщик мусора не включился, у вас может быть 3+ копии документа в памяти: в строителе строк, в строке и в XmlDocument.

Намного лучше сделать что-то вроде:

XmlDocument xDoc = new XmlDocument();
Stream dataStream;
try {
  dataStream = response.GetResponseStream();
  xDoc.Load(dataStream);
} catch {
 MessageBox.Show("There was an error with the communication.");
} finally {
  if(dataStream != null)
    dataStream.Dispose();
}
0 голосов
/ 24 сентября 2010

Вы пытались загрузить из потока, а не из строки (это отличается от записи в поток, потому что в вашем примере вы все еще пытаетесь загрузить все это сразу в память с XmlDocument)?

Существуют и другие компоненты .NET для файлов XML, которые работают с XML в виде потока, а не загружают его все сразу.Проблема в том, что .LoadXML, вероятно, пытается обработать весь документ одновременно, загружая его в память.Мало того, но вы уже загрузили его в строку, поэтому он существует в двух разных формах в памяти, что еще больше увеличивает вероятность того, что вам не хватит свободной непрерывной памяти.

Вам нужны некоторыеспособ прочитать его в виде потока в поток через XmlReader, так что вы можете начать чтение XML-документа по кусочкам, не загружая все это в память.Конечно, у этого подхода есть ограничения, потому что XmlReader предназначен только для пересылки и только для чтения, и будет ли он работать, зависит от того, что вы хотите делать с XML после его загрузки.

...