2012-06-13 21 views
5

Tôi đã viết một số mã tải một tài liệu XML sử dụng một đối tượng XmlDocument để đếm các nút của nó. Đây là phương pháp:C#: phương pháp đóng của Xml.Load (tập tin)

XmlDocument xml = new XmlDocument(); 
xml.Load(textBox1.Text); 
XmlNodeList nodes = xml.SelectNodes("//File"); 
foreach (XmlNode node in nodes) 
{ 
    number_of_childs++; 
} 

Vấn đề mà tôi đang gặp phải là khi nhập một tệp lớn, phải mất 700MB RAM. Nếu sau đó tôi cố gắng thực hiện một số thao tác trên tệp, hoặc thậm chí đọc từ nó để hiển thị dữ liệu của nó trong một ListView, ứng dụng sẽ mất khoảng 2GB RAM. Vì vậy, tôi đã tự hỏi, là có một phương pháp đóng XmlDocument và giải phóng bộ nhớ của nó, phát hành RAM. Nó giống như nó quên mất nội dung của nó khỏi bộ nhớ.

Trả lời

12

No. Lớp XmlDocument không triển khai IDisposable, vì vậy không có cách nào buộc nó giải phóng tài nguyên của nó theo ý thích. Nếu bạn thực sự cần phải ngay lập tức giải phóng bộ nhớ được sử dụng bởi XmlDocument, cách duy nhất để làm điều đó sẽ được thực hiện như sau:

thu
nodes = null; 
xml = null; 
GC.Collect(); 

Rác hoạt động trên một chủ đề riêng biệt, vì vậy nó có thể vẫn không xảy ra ngay lập tức. Buộc thực hiện thu gom rác thải để xảy ra đồng bộ, trước khi tiếp tục thực hiện các mã của bạn, bạn cũng phải gọi WaitForPendingFinalizers, như vậy:

nodes = null; 
xml = null; 
GC.Collect(); 
GC.WaitForPendingFinalizers(); 

XmlDocument luôn tải toàn bộ tài liệu vào bộ nhớ cùng một lúc. Nếu bạn chỉ muốn lặp qua các nút trong tài liệu dưới dạng luồng, chỉ tải từng chút một, đó là những gì mà lớp XmlReader là dành cho. Tuy nhiên, bạn mất rất nhiều chức năng theo cách đó. Ví dụ, không có cách nào để chọn các nút thông qua XPath, như bạn làm trong ví dụ của bạn. Với XmlReader, bạn phải viết logic của riêng mình để xác định vị trí của tài liệu và liệu nó có khớp với những gì bạn đang tìm kiếm hay không.

+0

Cảm ơn bạn đã cung cấp thông tin đó, nhưng nó không hoạt động, tôi đã áp dụng đoạn mã của bạn nhưng nó vẫn giữ lại cùng một lượng bộ nhớ. –

+0

@ R.Vector xem chỉnh sửa của tôi. –

+0

Đúng vậy, nhưng bước thứ hai của ứng dụng là đọc mọi nút và nhập nó vào một listview, vì vậy vấn đề vẫn tồn tại, nhưng nếu tôi có thể đọc từng nút của xml và giải phóng không gian của nó khỏi bộ nhớ khi nó lưu trữ thành công một nơi nào đó <<< theo cách đó sẽ tốt hơn cho việc quản lý bộ nhớ. –

2

Nếu bạn không phải thao tác XML, chỉ cần đọc XML bằng cách sử dụng XMLReader, đó là nhanh chóng và nhanh nhất, với hoạt động ít bộ nhớ dữ dội hơn.

1

Không cần thiết lập đối tượng của bạn thành rỗng. GC sẽ có thể cho biết liệu Tài liệu không còn được sử dụng nữa trên tài liệu của chính nó hay không. Điều này sẽ tự động xảy ra khi cần bộ nhớ nhưng nếu bạn muốn xóa nó ngay lập tức, hãy gọi GC.Collect(). Xem this thread để thảo luận thêm.

+1

Tôi đồng ý rằng nó thường không phải là một mối quan tâm lớn và GC cuối cùng sẽ phát hành bộ nhớ trên riêng của nó, nhưng nếu bạn sẽ gọi bộ thu gom rác bằng tay, bạn phải đặt biến thành null trước khi gọi GC.Collect, nếu không thì đối tượng sẽ vẫn được tham chiếu và nó sẽ không được thu thập. –

+0

@Steven Doggart, tuyên bố của bạn chỉ đúng trong các bản dựng Debug. Trong bản phát hành Bản phát hành, đặt thành null là không cần thiết - GC đủ thông minh để thấy rằng nó không còn được tham chiếu mà không đặt nó thành rỗng. Xem http://stackoverflow.com/questions/5545288/garbage-collection-of-orphaned-objects-tree-nodes-works-for-the-release-exe chẳng hạn. –

+0

@MattSmith Thật ngạc nhiên và thú vị. Có phải vì bản xây dựng Bản phát hành, theo mặc định, bao gồm các tối ưu hóa bổ sung sẽ tự động đặt biến thành 'null' ngay sau khi nó không còn được sử dụng hay cái gì đó? –

Các vấn đề liên quan