關于VC# 如何提高運行效率
大家都知道.NET 讓我們開發程序更加的簡單,特別是對與企業性的大型軟件的開發,它和JAVA一樣運用了GC(垃圾回收) 的機制,有了垃圾回收就可以丟掉在C或C++ 中痛苦的指針, 可以不用花心思去關注內存是不是已經釋放,可以說給程序員減輕了負擔。 我在這不說關于GC是不是好,GC也有它自己的缺點,如已經不必要用的內存不會提前釋放,或多或少的浪費了內存,我不想說C#中采用GC 有多成功,但是從我自己開發的經歷來,C#的效率很讓人失望,同一功能用C++ 實現比C#實現更節約內存,我沒有用C#開發過大的程序,不知道究竟C#對內存的要求有多大,按照我的一程序分析, 有垃圾回收的機制的語言是C++ 的內存的3-20倍,怎么樣才能提高C#開發的程序的運行效率,怎么才可以節約空間呢?
縱所周知,算法是程序的核心,我們無法改變語言自己本身特有的,只有從我們算法來著手來想辦法!同樣的能夠可以用不同的思路來實現,所謂條條大路同羅馬,大家都知道,也許我們所缺少的是思考,我們作為程序員 本來就做思考的活動,能為一個問題思考可以說是一件樂事! 下面我說一個例子,關于VC#的使用,對于同一個問題可以使用不同的方法
我們現在面臨的問題如下(假設) 要用TreeView 做一個類似資源瀏覽器的東西
說到算法很簡單:就是遍歷電腦里的文件,并且添加到TreeView 接點中!
一種最簡單的(核心)代碼如下:
private void button1_Click(object sender, System.EventArgs e) { try { DirectoryInfo ainfo=new DirectoryInfo("C:\\"); TreeNode nan=new TreeNode(ainfo.FullName); this.treeView1.Nodes.Add(nan); addNode(nan); } catch(System.IO.DirectoryNotFoundException eDnfa) { MessageBox.Show(eDnfa.Message); } }
private void addNode(TreeNode tn) { DirectoryInfo di=new DirectoryInfo(tn.Text); DirectoryInfo[] aTemp=di.GetDirectories(); if (aTemp.Length>0) foreach(DirectoryInfo d in aTemp) { TreeNode node=new TreeNode(d.FullName); tn.Nodes.Add(node); addNode(node); } FileInfo[] sFiles=di.GetFiles(); foreach(FileInfo f in sFiles ) { TreeNode node=new TreeNode(f.FullName); tn.Nodes.Add(node); } }
上面的代碼顯示C盤的全部文件是TREEVIEW中,大家可以分析它執行的先后順序:
button1 的 Click 引發后執行后面的操作,然后調用addNode(TreeNode tn) 方法!仔細看里面,其實用到了遞歸, 首先是 把“C:\\” 加入到根接點,然后訪問C盤第一個文件夾,加入到樹中,然后訪問C盤第一個文件夾下的第一個文件夾,加入到數中,以次遞歸,當到了盡頭,然后再返回加第而個文件,形象的說是做S形循環! 我無法用圖來說明具體情況,也許比較難理解,我想只要自己仔細思考是可以想出來,我們要永遠記住,程序員這一個職業就是 思考的 職業! 還要創新!
毫無疑問,上面的算法是正確的,但是到最后使用了多少內存呢,全部的接點都加到了Treeview 中,無疑這樣使用了很多空間! 更郁悶的是如果我們要操作軟件,必須等軟件已經做完上一部分的事才響應我們接下來來操作, 上面的方法會導致我們的軟件有 死機現象 有沒有更好的辦法?
問題就出現我們使用了常規的想法,就差一點自己的改動!
我們仔細想一想,在TreeView中,我們想要看見(這里指的看見是指人眼可以看他在樹中)所有接點需要我們用鼠標去展開,當我們沒有展開接點呢(沒有展開接點前有必要就加到樹中嗎)? 上面的算法是一次性的初始化了全部了的接點,只要我們不一次性初始化就可以了!
看下面的方法:
private void Form1_Load(object sender, System.EventArgs e) { this.treeView1 .Nodes .Clear (); DirectoryInfo my=new DirectoryInfo ("c:\\"); TreeNode nan=new TreeNode(@my.FullName); this.treeView1.Nodes.Add(nan); addMyTreeView(nan);
}
private void addMyTreeView(TreeNode mNode) { try { DirectoryInfo di=new DirectoryInfo(@mNode.Text); DirectoryInfo[] aTemp=di.GetDirectories(); for(int i=0;i<aTemp.Length ;i++) { TreeNode my2=new TreeNode (@aTemp[i].FullName ); mNode.Nodes .Add(my2); //addMyTreeView(my2); this is a bad method! DirectoryInfo di2=new DirectoryInfo(@my2.Text ); DirectoryInfo[] aTemp2=di2.GetDirectories(); for(int j=0;j<aTemp2.Length ;j++) { TreeNode my3=new TreeNode (@aTemp2[j].FullName ); my2.Nodes .Add (my3); }
} } catch(Exception ex) { } }
private void treeView1_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e) { e.Node.Nodes.Clear(); this.addMyTreeView(e.Node); }
private void treeView1_BeforeExpand(object sender, System.Windows.Forms.TreeViewCancelEventArgs e) { e.Node.Nodes.Clear(); this.addMyTreeView(e.Node); } 上面的是我們充分的運用了treeView控件的所有方法 上面的思路如下: 在窗體Load的 加入“c:\\” 接點,然后調用 private void addMyTreeView(TreeNode mNode),但是在這里面用了兩層循環,也就 把 相對于C 盤的 文件加入了兩層,(C盤的文件我們可以看成是一級一級的目錄), 當 AfterSelect 發生時 這次調用 addMyTreeView(TreeNode mNode) ,當BeforeExpand 時清除 接點 仔細比較第種算法,我們可以看出第二種比第一種更方便,第二種也沒有增加什么技術難度,只是 換了一了下思維方式!
你也許會說我第一種方法是有意浪費空間的,當然我只是為做一個有對比的演示,我相信大家還可以在我第二中方法上更加優化!
軟件開發不是簡單的復制和粘貼,更加要思考, 不要輕視小程序的資源問題,也許在對大程序時就可以節約不必要的空間時間浪費!
今天就
|