句柄只是用來標識應用程序中的不同對象和同類中的不同的實例的一個數字,通常情況下,句柄值對普通用戶毫無用處,但是句柄數量卻可以間接反映出一個程序里產生的對象實例的多少。句柄數越多,代表程序里new 出來的對象越多。但是在c#里,經常會遇到句柄數莫名其妙的增加。
DateTime lastTime1 = DateTime.Now.AddHours(1); while (true) { var a = lastTime1 - DateTime.Now; if (a.TotalHours <= 0) { break; } //DoSomething! Thread.Sleep(1000); }
在DoSomeThing里,如果用一個委托,去更新窗體控件,會發現任務管理器里的“句柄數”一欄,值會一點點的增加。而且通常都不怎么降。
比如:
richTextBox1.Invoke(new EventHandler(delegate { label3.Text ="xxxx"; }));
不管這個匿名委托里有沒有代碼,句柄數都會增加
但是如果使用上下文同步對象給控件發送消息,這個問題就解決了
_syncContext.Post(ReFreshUI, a); private void ReFreshUI(object state) { try { label3.Text = state.ToString(); } catch { } }
而且我還發現一個有意思的問題。
那就是如果在循環里,添上對 StatusStripLabel控件進行更新的代碼,句柄數也會增加,也是沒有要停的意思。幾分鍾時間里居然升到了1000多。如果將這個控件換成Label控件,那么句柄數會保持不變。這算不算是StatusStripLabel這個控件的bug呢。
另外,還有一個可能導致句柄數增加的。就是 很多人都會和我一樣,寫上這樣的代碼:
socket = new Socket(AddressFamily.InterNetwork, SocketType, SocketType == SocketType.Dgram ? ProtocolType.Udp : ProtocolType.Tcp); IAsyncResult result = socket.BeginConnect(remoteEP, null, null); if (result.AsyncWaitHandle.WaitOne(timeout, false) && socket.Connected) { result.AsyncWaitHandle.Close(); RemoteEndPoint = remoteEP; return true; }
經過測試發現。只要跑一輪這個代碼,句柄數也會增加幾個。而且跑完了也不會降下來。后面我想了下,result.AsyncWaitHandle就是一個WaitHandle對象,而我們知道這個對象是需要顯式地釋放掉才行的。
如果加上 result.AsyncWaitHandle.Close();問題就可以完美的解決了,句柄數一般都不會上升,甚至可能降一點。