您的位置:首页 > 编程语言 > C#

【C#Winform】一个多线程扫描本地磁盘目录文件个数的Demo

2013-04-11 11:05 483 查看
扫描本地磁盘目录是个巨大的工程,扫描文件个数更是个巨大的工程。

单线程在处理大型任务的时候是很难胜任的 或者说很难有什么可接受的效率

多线程比单线程的最大优势是可以把巨大的任务分割成小任务并发进行

然后把每个线程的执行结果汇总

其实巨大的任务分得越细 多线程就比单线程约有优势



下面将来完成上图界面的扫描计数功能

其中左右两边的加载树形结构的控件是TreeView

下面显示消息的是ListView 其他的控件很明显 就不说明了。

好吧 直接看代码:

public partial class fCodeManage : Form
{
List<System.Threading.Thread> ts;
//System.Text.StringBuilder msg = new StringBuilder();
Color treeNodeColor;
public fCodeManage()
{
InitializeComponent();
}

private void TestTool_Load(object sender, EventArgs e)
{
Init();
}
protected void Init() {
this.tvDir.Nodes.Clear();
this.tvSelDir.Nodes.Clear();
this.tvDir.Nodes.Add(new TreeNode("我的电脑/My PC"));
this.tvSelDir.Nodes.Add(new TreeNode("选择目录/Selected Directory"));
DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
this.tvDir.TopNode.ToolTipText = string.Format("拥有{0}个磁盘", drives.Length);
foreach (DriveInfo di in drives)
{
if (di.IsReady)
{
this.tvDir.TopNode.Nodes.Add(new TreeNode(di.Name, new TreeNode[] { new TreeNode() }));
}
}
this.tvDir.TopNode.Expand();

}
private void bAdd_Click(object sender, EventArgs e)
{
TreeNode selNode = this.tvDir.SelectedNode;
if (selNode == null) {
MessageBox.Show("请选择一个节点");
return;
}
if (treeNodeColor == Color.Empty) {
treeNodeColor = selNode.ForeColor;
}
List<TreeNode> findResult = new List<TreeNode>();
foreach (TreeNode tn in this.tvSelDir.TopNode.Nodes)
{
if (tn.Text.IndexOf(selNode.Text) != -1)
{
if (tn.Tag != null && ((TreeNode)tn.Tag == selNode || SearchNode(selNode.Nodes, (TreeNode)tn.Tag)))
{
findResult.Add(tn);
}
}
}
foreach (TreeNode tn in findResult) {
this.tvSelDir.TopNode.Nodes.Remove(tn);
((TreeNode)tn.Tag).Nodes.Add(tn);
}
if (selNode != this.tvDir.TopNode)
{
selNode.Tag = selNode.Parent;
}
this.tvDir.Nodes.Remove(selNode);
this.tvSelDir.TopNode.Nodes.Add(selNode);
this.tvSelDir.TopNode.Expand();

}

private void bDel_Click(object sender, EventArgs e)
{
TreeNode selNode = this.tvSelDir.SelectedNode;
if (selNode == null)
{
MessageBox.Show("请选择一个节点");
return;
}
if (selNode == this.tvSelDir.TopNode||selNode.Parent!=this.tvSelDir.TopNode) {
MessageBox.Show("您不能删除该节点");
return;
}
selNode.Parent.Nodes.Remove(selNode);
if (selNode.Tag != null)
{
((TreeNode)selNode.Tag).Nodes.Add(selNode);
}
else
{
this.tvDir.Nodes.Add(selNode);
}
}

protected bool SearchNode(TreeNodeCollection nodeList, TreeNode findNode)
{
foreach (TreeNode tn in nodeList) {
if (tn == findNode || tn.Text == findNode.Text)
{
return true;
}
if(findNode.Text.IndexOf(tn.Text)!=-1){
if (tn.Nodes.Count > 0)
{
return SearchNode(tn.Nodes, findNode);
}
}
}
return false;
}

private void tvDir_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{

if (string.IsNullOrEmpty(e.Node.ToolTipText))
{
try
{
string[] dirs = System.IO.Directory.GetDirectories(e.Node.Text);
e.Node.ToolTipText = string.Format("拥有{0}个子目录", dirs.Length);
e.Node.Nodes.Clear();
foreach (string dir in dirs)
{
e.Node.Nodes.Add(new TreeNode(dir, new TreeNode[] { new TreeNode() }));
}
}
catch(Exception ex) {
e.Node.ToolTipText = string.Empty;
e.Node.Nodes.Clear();
e.Node.Nodes.Add(new TreeNode());
this.lbMsg.Items.Add(string.Format("获取{1}子目录发生错误,请稍候再试,错误内容为:{0}", ex.Message,e.Node.Text));
}
}
}

private void tvSelDir_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
if (e.Node == ((TreeView)sender).TopNode) {
return;
}
tvDir_BeforeExpand(sender, e);
}

private void bReload_Click(object sender, EventArgs e)
{
Init();
}

private void tvSelDir_BeforeSelect(object sender, TreeViewCancelEventArgs e)
{
if (e.Node.Parent != ((TreeView)sender).TopNode) {
e.Cancel = true;
}
}

private void bClose_Click(object sender, EventArgs e)
{
this.Close();
}

private void TestTool_FormClosing(object sender, FormClosingEventArgs e)
{
this.Dispose(true);
Application.Exit();
System.Environment.Exit(0);
}

private void tvDir_BeforeSelect(object sender, TreeViewCancelEventArgs e)
{
if (e.Node == ((TreeView)sender).TopNode)
{
e.Cancel = true;
}
}

private void bRun_Click(object sender, EventArgs e)
{
if (this.tvSelDir.TopNode.Nodes.Count <= 0) {
MessageBox.Show("没有要检查的目录");
return;
}
int threadCount = Convert.ToInt32(this.nupThreadCount.Value);
this.ts = new List<System.Threading.Thread>();

for (int i = 0; i < threadCount; i++) {
ts.Add(new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(DoWork)));
ts[i].Name = string.Format("iRightCodeManage_{0}", i+1);
ts[i].Start(ts[i]);
}
if (this.lbMsg.Items.Count > 0) {
this.lbMsg.Items.Add("---------------------------");
}
this.lbMsg.Items.Add(string.Format("{0}个线程{1}开始运行,请耐心等待处理结果!", threadCount,System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
}

protected void DoWork(object thread)
{
System.Threading.Thread currentThreading = thread as System.Threading.Thread;
string tIndex = currentThreading.Name.Split('_')[1];
TreeNode tn2Work = null;
do
{
tn2Work = null;
lock (this.tvSelDir.TopNode.Nodes)
{
foreach (TreeNode tn in this.tvSelDir.TopNode.Nodes)
{
if (tn.ForeColor != Color.Red && tn.ForeColor != Color.Green)
{
tn.ForeColor = Color.Red;
tn2Work = tn;
break;
}
}
}
if (tn2Work != null)
{
int fileCount = 0;
DoWordOfDir(tn2Work.Text, ref fileCount);
//msg.AppendFormat("目录【{0}】有{1}个文件", tn.Text, fileCount);
this.lbMsg.Items.Add(string.Format("第{2}个线程处理完毕,目录【{0}】有{1}个文件", tn2Work.Text, fileCount, tIndex));
tn2Work.ForeColor = Color.Green;
}
} while (tn2Work != null);
this.lbMsg.Items.Add(string.Format("第{0}个线程已终止", tIndex));
ts.Remove(currentThreading);
currentThreading.Interrupt();
if (ts == null || ts.Count <= 0)
{
foreach (TreeNode tn in this.tvSelDir.TopNode.Nodes)
{
tn.ForeColor = treeNodeColor;
}
this.lbMsg.Items.Add(string.Format("全部线程在{0}完成任务。", System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
this.lbMsg.Items.Add("---------------------------");
}
currentThreading.Abort();
}
protected void DoWordOfDir(string dirPath,ref int fileCount) {
try
{
System.IO.DirectoryInfo fi = new System.IO.DirectoryInfo(dirPath);
fi.SetAccessControl(new System.Security.AccessControl.DirectorySecurity(dirPath, System.Security.AccessControl.AccessControlSections.Access));
FileSystemInfo[] fsis = fi.GetFileSystemInfos();
foreach (FileSystemInfo fsi in fsis)
{
if (fsi is System.IO.DirectoryInfo)
{
DoWordOfDir(fsi.FullName, ref fileCount);
}
else if (fsi is System.IO.FileInfo)
{
fileCount++;
}
}
}
catch
{ }

}
private void bThreadClear_Click(object sender, EventArgs e)
{
if (this.ts == null || this.ts.Count <= 0) {
MessageBox.Show("没有要清除的线程!");
return;
}
foreach (System.Threading.Thread t in ts) {
if (t != null)
{
t.Abort();
}
}
ts = null;
MessageBox.Show("线程清除完毕!");
}

private void bMsgClear_Click(object sender, EventArgs e)
{
this.lbMsg.Items.Clear();
}
}


此代码测试很稳定 暂时没有发现什么bug

如果有问题 可以回复我
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: