【C#Winform】一个多线程扫描本地磁盘目录文件个数的Demo
扫描本地磁盘目录是个巨大的工程,扫描文件个数更是个巨大的工程。
单线程在处理大型任务的时候是很难胜任的 或者说很难有什么可接受的效率
多线程比单线程的最大优势是可以把巨大的任务分割成小任务并发进行
然后把每个线程的执行结果汇总
其实巨大的任务分得越细 多线程就比单线程约有优势
下面将来完成上图界面的扫描计数功能
其中左右两边的加载树形结构的控件是TreeView
下面显示消息的是ListView 其他的控件很明显 就不说明了。
好吧 直接看代码:
1 public partial class fCodeManage : Form 2 { 3 List<System.Threading.Thread> ts; 4 //System.Text.StringBuilder msg = new StringBuilder(); 5 Color treeNodeColor; 6 public fCodeManage() 7 { 8 InitializeComponent(); 9 } 10 11 private void TestTool_Load(object sender, EventArgs e) 12 { 13 Init(); 14 } 15 protected void Init() { 16 this.tvDir.Nodes.Clear(); 17 this.tvSelDir.Nodes.Clear(); 18 this.tvDir.Nodes.Add(new TreeNode("我的电脑/My PC")); 19 this.tvSelDir.Nodes.Add(new TreeNode("选择目录/Selected Directory")); 20 DriveInfo[] drives = System.IO.DriveInfo.GetDrives(); 21 this.tvDir.TopNode.ToolTipText = string.Format("拥有{0}个磁盘", drives.Length); 22 foreach (DriveInfo di in drives) 23 { 24 if (di.IsReady) 25 { 26 this.tvDir.TopNode.Nodes.Add(new TreeNode(di.Name, new TreeNode[] { new TreeNode() })); 27 } 28 } 29 this.tvDir.TopNode.Expand(); 30 31 } 32 private void bAdd_Click(object sender, EventArgs e) 33 { 34 TreeNode selNode = this.tvDir.SelectedNode; 35 if (selNode == null) { 36 MessageBox.Show("请选择一个节点"); 37 return; 38 } 39 if (treeNodeColor == Color.Empty) { 40 treeNodeColor = selNode.ForeColor; 41 } 42 List<TreeNode> findResult = new List<TreeNode>(); 43 foreach (TreeNode tn in this.tvSelDir.TopNode.Nodes) 44 { 45 if (tn.Text.IndexOf(selNode.Text) != -1) 46 { 47 if (tn.Tag != null && ((TreeNode)tn.Tag == selNode || SearchNode(selNode.Nodes, (TreeNode)tn.Tag))) 48 { 49 findResult.Add(tn); 50 } 51 } 52 } 53 foreach (TreeNode tn in findResult) { 54 this.tvSelDir.TopNode.Nodes.Remove(tn); 55 ((TreeNode)tn.Tag).Nodes.Add(tn); 56 } 57 if (selNode != this.tvDir.TopNode) 58 { 59 selNode.Tag = selNode.Parent; 60 } 61 this.tvDir.Nodes.Remove(selNode); 62 this.tvSelDir.TopNode.Nodes.Add(selNode); 63 this.tvSelDir.TopNode.Expand(); 64 65 } 66 67 private void bDel_Click(object sender, EventArgs e) 68 { 69 TreeNode selNode = this.tvSelDir.SelectedNode; 70 if (selNode == null) 71 { 72 MessageBox.Show("请选择一个节点"); 73 return; 74 } 75 if (selNode == this.tvSelDir.TopNode||selNode.Parent!=this.tvSelDir.TopNode) { 76 MessageBox.Show("您不能删除该节点"); 77 return; 78 } 79 selNode.Parent.Nodes.Remove(selNode); 80 if (selNode.Tag != null) 81 { 82 ((TreeNode)selNode.Tag).Nodes.Add(selNode); 83 } 84 else 85 { 86 this.tvDir.Nodes.Add(selNode); 87 } 88 } 89 90 protected bool SearchNode(TreeNodeCollection nodeList, TreeNode findNode) 91 { 92 foreach (TreeNode tn in nodeList) { 93 if (tn == findNode || tn.Text == findNode.Text) 94 { 95 return true; 96 } 97 if(findNode.Text.IndexOf(tn.Text)!=-1){ 98 if (tn.Nodes.Count > 0) 99 { 100 return SearchNode(tn.Nodes, findNode); 101 } 102 } 103 } 104 return false; 105 } 106 107 private void tvDir_BeforeExpand(object sender, TreeViewCancelEventArgs e) 108 { 109 110 if (string.IsNullOrEmpty(e.Node.ToolTipText)) 111 { 112 try 113 { 114 string[] dirs = System.IO.Directory.GetDirectories(e.Node.Text); 115 e.Node.ToolTipText = string.Format("拥有{0}个子目录", dirs.Length); 116 e.Node.Nodes.Clear(); 117 foreach (string dir in dirs) 118 { 119 e.Node.Nodes.Add(new TreeNode(dir, new TreeNode[] { new TreeNode() })); 120 } 121 } 122 catch(Exception ex) { 123 e.Node.ToolTipText = string.Empty; 124 e.Node.Nodes.Clear(); 125 e.Node.Nodes.Add(new TreeNode()); 126 this.lbMsg.Items.Add(string.Format("获取{1}子目录发生错误,请稍候再试,错误内容为:{0}", ex.Message,e.Node.Text)); 127 } 128 } 129 } 130 131 private void tvSelDir_BeforeExpand(object sender, TreeViewCancelEventArgs e) 132 { 133 if (e.Node == ((TreeView)sender).TopNode) { 134 return; 135 } 136 tvDir_BeforeExpand(sender, e); 137 } 138 139 private void bReload_Click(object sender, EventArgs e) 140 { 141 Init(); 142 } 143 144 private void tvSelDir_BeforeSelect(object sender, TreeViewCancelEventArgs e) 145 { 146 if (e.Node.Parent != ((TreeView)sender).TopNode) { 147 e.Cancel = true; 148 } 149 } 150 151 private void bClose_Click(object sender, EventArgs e) 152 { 153 this.Close(); 154 } 155 156 private void TestTool_FormClosing(object sender, FormClosingEventArgs e) 157 { 158 this.Dispose(true); 159 Application.Exit(); 160 System.Environment.Exit(0); 161 } 162 163 private void tvDir_BeforeSelect(object sender, TreeViewCancelEventArgs e) 164 { 165 if (e.Node == ((TreeView)sender).TopNode) 166 { 167 e.Cancel = true; 168 } 169 } 170 171 private void bRun_Click(object sender, EventArgs e) 172 { 173 if (this.tvSelDir.TopNode.Nodes.Count <= 0) { 174 MessageBox.Show("没有要检查的目录"); 175 return; 176 } 177 int threadCount = Convert.ToInt32(this.nupThreadCount.Value); 178 this.ts = new List<System.Threading.Thread>(); 179 180 for (int i = 0; i < threadCount; i++) { 181 ts.Add(new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(DoWork))); 182 ts[i].Name = string.Format("iRightCodeManage_{0}", i+1); 183 ts[i].Start(ts[i]); 184 } 185 if (this.lbMsg.Items.Count > 0) { 186 this.lbMsg.Items.Add("---------------------------"); 187 } 188 this.lbMsg.Items.Add(string.Format("{0}个线程{1}开始运行,请耐心等待处理结果!", threadCount,System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))); 189 } 190 191 protected void DoWork(object thread) 192 { 193 System.Threading.Thread currentThreading = thread as System.Threading.Thread; 194 string tIndex = currentThreading.Name.Split('_')[1]; 195 TreeNode tn2Work = null; 196 do 197 { 198 tn2Work = null; 199 lock (this.tvSelDir.TopNode.Nodes) 200 { 201 foreach (TreeNode tn in this.tvSelDir.TopNode.Nodes) 202 { 203 if (tn.ForeColor != Color.Red && tn.ForeColor != Color.Green) 204 { 205 tn.ForeColor = Color.Red; 206 tn2Work = tn; 207 break; 208 } 209 } 210 } 211 if (tn2Work != null) 212 { 213 int fileCount = 0; 214 DoWordOfDir(tn2Work.Text, ref fileCount); 215 //msg.AppendFormat("目录【{0}】有{1}个文件", tn.Text, fileCount); 216 this.lbMsg.Items.Add(string.Format("第{2}个线程处理完毕,目录【{0}】有{1}个文件", tn2Work.Text, fileCount, tIndex)); 217 tn2Work.ForeColor = Color.Green; 218 } 219 } while (tn2Work != null); 220 this.lbMsg.Items.Add(string.Format("第{0}个线程已终止", tIndex)); 221 ts.Remove(currentThreading); 222 currentThreading.Interrupt(); 223 if (ts == null || ts.Count <= 0) 224 { 225 foreach (TreeNode tn in this.tvSelDir.TopNode.Nodes) 226 { 227 tn.ForeColor = treeNodeColor; 228 } 229 this.lbMsg.Items.Add(string.Format("全部线程在{0}完成任务。", System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))); 230 this.lbMsg.Items.Add("---------------------------"); 231 } 232 currentThreading.Abort(); 233 } 234 protected void DoWordOfDir(string dirPath,ref int fileCount) { 235 try 236 { 237 System.IO.DirectoryInfo fi = new System.IO.DirectoryInfo(dirPath); 238 fi.SetAccessControl(new System.Security.AccessControl.DirectorySecurity(dirPath, System.Security.AccessControl.AccessControlSections.Access)); 239 FileSystemInfo[] fsis = fi.GetFileSystemInfos(); 240 foreach (FileSystemInfo fsi in fsis) 241 { 242 if (fsi is System.IO.DirectoryInfo) 243 { 244 DoWordOfDir(fsi.FullName, ref fileCount); 245 } 246 else if (fsi is System.IO.FileInfo) 247 { 248 fileCount++; 249 } 250 } 251 } 252 catch 253 { } 254 255 } 256 private void bThreadClear_Click(object sender, EventArgs e) 257 { 258 if (this.ts == null || this.ts.Count <= 0) { 259 MessageBox.Show("没有要清除的线程!"); 260 return; 261 } 262 foreach (System.Threading.Thread t in ts) { 263 if (t != null) 264 { 265 t.Abort(); 266 } 267 } 268 ts = null; 269 MessageBox.Show("线程清除完毕!"); 270 } 271 272 private void bMsgClear_Click(object sender, EventArgs e) 273 { 274 this.lbMsg.Items.Clear(); 275 } 276 }
此代码测试很稳定 暂时没有发现什么bug
如果有问题 可以回复我