【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

如果有问题 可以回复我

原文地址:https://www.cnblogs.com/yomho/p/CSWinformThreading.html