我做了一个应用程序从给定的sharepoint站点下载一个文件夹,但是当我点击Connect按钮时它消耗的内存超过600,000K,任何人都可以给出建议来改进我的代码吗?
我试图调试我的表单,问题出现在方法“private void MapWebs(SPWebCollection webList,TreeNode webparentNode)”中,它一次又一次地调用自己来遍历每个网络及其子网,但我检查了当我点击连接时它开始,它通过代码行
using (SPSite CurrentSite = new SPSite(tbSite.Text))
内存使用量从20,000 K到40,000 K(大约)
要运行此应用程序,您必须在您的PC上安装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] ...和if语句”)
注意:调用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
答案 0 :(得分:3)
我在这里看到两个问题:
您正在迭代SPWeb
时处置SPWeb.Webs
,但您在TreeNode.Tag
上保留了引用。通过节点的标记访问已处置的SPWeb
时,SharePoint将再次“打开”Web。 =&GT;记忆泄漏
由于您正在递归调用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