Слишком много памяти для приложения Windows - PullRequest
0 голосов
/ 22 декабря 2011

Я подал заявку на загрузку папки с заданного сайта sharepoint, но после того, как я нажму кнопку «Подключить», она потребляет память более 600 000 КБ, кто-нибудь может предложить улучшить мой код?

Я пытался отладитьмоя форма и проблема связаны с методом «private void MapWebs (SPWebCollection webList, TreeNode webparentNode)», где он снова и снова обращается к себе, чтобы пройти через каждую отдельную сеть и ее подчиненную сеть, однако я проверил в начале, когда я нажимаю на соединениеон проходит через строку кода

using (SPSite CurrentSite = new SPSite(tbSite.Text))

Использование памяти увеличивается от 20 000 К до 40 000 К (приблизительно)

Чтобы запустить это приложение, у вас должен быть установлен sharepoint на вашем ПК, напримерэтого типа приложения находится по этой ссылке,

введите описание ссылки здесь

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint;
using System.IO;

namespace WindowsFormsApplication3
{
    public partial class MainWindow : Form
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    //Connects to Sharepoint site provided and populates Webs and Subwebs and subwebs....
    private void bConnect_Click(object sender, EventArgs e)
    {
            //Getting current site
            using (SPSite CurrentSite = new SPSite(tbSite.Text))
            {
                //Opening TopLevel Web for Site given
                using (SPWeb TopLevelWeb = CurrentSite.OpenWeb())
                {
                    //Clearing all the nodes in TreeWeb
                    TreeWeb.Nodes.Clear();
                    //Creating a root (First Node for webtree) which will be Top Level web's title
                    TreeNode rootWebNode = new TreeNode(TopLevelWeb.Title);
                    //Giving node a tag, which will be used later on in order to get value of node
                    rootWebNode.Tag = TopLevelWeb;
                    //Check if Top Level Web got any Sub webs if it does, it will create a new node for them
                    //Calls Map Webs to check for more sub webs + mapping them on webtree as nodes
                    foreach (SPWeb CurrentWeb in TopLevelWeb.Webs)
                    {
                        try
                        {
                            TreeNode webNode = new TreeNode(CurrentWeb.Title);
                            webNode.Tag = CurrentWeb;
                            MapWebs(CurrentWeb.Webs, webNode);
                            TreeWeb.Nodes.Add(webNode);
                        }
                        finally 
                        {
                            if (CurrentWeb != null)
                                CurrentWeb.Dispose();
                        }
                    }
                }
            }
        }

    // Maps Webs and there sub webs on webtree
    private void MapWebs(SPWebCollection webList, TreeNode webparentNode)
    {
            for (var i = 0; i < webList.Count; i++)
            {
                TreeNode node = new TreeNode(webList[i].Name);

                using (SPWeb web = webList[i])
                {
                node.Tag = webList[i];
                    webparentNode.Nodes.Add(node);
                    if (webList[i].Webs.Count > 0)
                        MapWebs(webList[i].Webs, node);
                }
            }
            GC.Collect();
    }

    //when the form loads it clears the list and create new cloumns to be used
    private void MainWindow_Load(object sender, EventArgs e)
    {
        bFolder.Enabled = false;
        bConnect.Enabled = false;
        lvFiles.GridLines = true;
        lvFiles.View = View.Details;
        lvFiles.Columns.Add("Name", lvFiles.Width/4, HorizontalAlignment.Left);
        lvFiles.Columns.Add("Date Created", lvFiles.Width/3, HorizontalAlignment.Left);
        lvFiles.Columns.Add("Size", lvFiles.Width / 5, HorizontalAlignment.Left);
        lvFiles.Columns.Add("Time Last Modified", lvFiles.Width / 5, HorizontalAlignment.Left);
        if (lvFiles.View == View.Details && lvFiles.Columns.Count > 0)
            this.Width = lvFiles.Columns.Count * (lvFiles.Width / 2);
        lvFiles.Columns[lvFiles.Columns.Count - 1].Width = -2;
    }

    //creates directory for downloading folder
    private bool CreateDirectoryStructure(string baseFolder, string filepath)
    {
        if (!Directory.Exists(baseFolder)) return false;

        var paths = filepath.Split('/');

        for (var i = 0; i < paths.Length - 1; i++)
        {
            baseFolder = System.IO.Path.Combine(baseFolder, paths[i]);
            Directory.CreateDirectory(baseFolder);
        }
        return true;
    }

    //opens an dialog box for selecting path where selected folder will be downloaded
    private void bBrowse_Click(object sender, EventArgs e)
    {
        if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
        {
            this.tbDirectory.Text = folderBrowserDialog1.SelectedPath;
        }
    }

    //when a node is selected in webtree it checks for folders in it , + sub folders + folders......
    private void TreeWeb_AfterSelect(object sender, TreeViewEventArgs e)
    {
        TreeFolder.Nodes.Clear();
        TreeNode currentNode = TreeWeb.SelectedNode;
        using (SPWeb oWeb = (SPWeb)currentNode.Tag)
        {
            foreach (SPList list in oWeb.Lists)
            {
                if (list is SPDocumentLibrary && !list.Hidden)
                {
                    TreeNode folderNode = new TreeNode(list.Title);
                    folderNode.Text = string.Format("{0} ({1})", list.Title, list.ItemCount);
                    folderNode.Tag = list.RootFolder;

                    foreach (SPListItem listItem in list.Folders)
                    {
                        if (listItem.Folder != null)
                        {
                            TreeNode node = new TreeNode(listItem.Folder.Name);
                            node.Tag = listItem.Folder;
                            node.Text = string.Format("{0} ({1})", listItem.Folder.Name,
                                                 GetFilesCount(listItem.Folder));

                            MapFolders(listItem.Folder.SubFolders, node);
                            folderNode.Nodes.Add(node);
                        }
                    }

                    TreeFolder.Nodes.Add(folderNode);
                }
            }
        }
    }

    //Maps folder on foldertree
    private void MapFolders(SPFolderCollection folderList, TreeNode parentNode)
    {
        for (var i = 0; i < folderList.Count; i++)
        {
                TreeNode node = new TreeNode(folderList[i].Name);
                node.Text = string.Format("{0} ({1})", folderList[i].Name,
                                             GetFilesCount(folderList[i]));
                node.Tag = folderList[i];
                parentNode.Nodes.Add(node);

                if (folderList[i].SubFolders.Count > 0)
                    MapFolders(folderList[i].SubFolders, node);
        }
    }

    //Maps files in a folder to listview
    private void TreeFolder_AfterSelect(object sender, TreeViewEventArgs e)
    {
        lvFiles.Items.Clear();
        TreeNode currentNode = TreeFolder.SelectedNode;
        //if (currentNode != rotnode)
        //{
        double TotalSize = 0;
        SPFolder oFolder = (SPFolder)currentNode.Tag;
        foreach (SPFile oFile in oFolder.Files)
            {
                TotalSize += (oFile.Length)/1024/1024;

                ListViewItem LTI = new ListViewItem(oFile.Name.ToString());
                LTI.SubItems.Add(oFile.TimeCreated.ToString());
                LTI.SubItems.Add(oFile.Length.ToString());
                LTI.SubItems.Add(oFile.TimeLastModified.ToString());
                lvFiles.Items.Add(LTI);
            }
            label4.Text = TotalSize.ToString();
        //}
    }

    //download selected folder + validation
    private void bFolder_Click(object sender, EventArgs e)
    {
            TreeNode currentNode = TreeFolder.SelectedNode;
                SPFolder oFolder = (SPFolder)currentNode.Tag;
                foreach (SPFile file in oFolder.Files)
                {
                    if (CreateDirectoryStructure(tbDirectory.Text, file.Url))
                    {
                        var filepath = System.IO.Path.Combine(tbDirectory.Text, file.Url);
                        byte[] binFile = file.OpenBinary();
                        System.IO.FileStream fstream = System.IO.File.Create(filepath);
                        fstream.Write(binFile, 0, binFile.Length);
                        fstream.Close();
                    }
                }
    }

    //calculates files in selected folder
    private int GetFilesCount(SPFolder folder)
    {
        int fileCount = folder.Files.Count;
        foreach (SPFolder subfolder in folder.SubFolders)
        {
            fileCount += GetFilesCount(subfolder);
        }
        return fileCount;
    }

    //validation
    private void tbSite_TextChanged(object sender, EventArgs e)
    {
        if (tbSite.Text != "")
            bConnect.Enabled = true;
        else
            bConnect.Enabled = false;
    }

    //validation
    private void tbDirectory_TextChanged(object sender, EventArgs e)
    {
        if (tbDirectory.Text != "" && TreeFolder.Nodes.Count != 0)
            bFolder.Enabled = true;
        else
            bFolder.Enabled = false;
    }
}

}

Уже проверено с помощью SP Dispose checker, но оноговорит об этом (в строке метода MapWebs "node.tag = weblist [i] ... and if Statement")

Примечания: вызов Microsoft.SharePoint.SPWebCollection.get_Item и без переменной для перехвата возвращаемого значения. Дополнительная информация: http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_130

1 Ответ

3 голосов
/ 22 декабря 2011

Здесь я вижу две проблемы:

  1. Вы используете SPWeb, перебирая SPWeb.Webs, но сохраняете ссылку на TreeNode.Tag.При доступе к удаленному SPWeb через тег узла SharePoint снова «откроет» сеть.=> Утечка памяти

  2. Поскольку вы вызываете рекурсивный метод MapWebs, у вас одновременно открыты SPWeb объектов:

    Root -> open
      Child 1 -> open
        Child 1.1 -> open
            Child 1.1.1 -> open
        Child 1.2
        Child 1.3
        Child 1.4
    Child 2
    Child 3
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...