下面有從淺入深的6個問題,您可以嘗試回答一下
- 一個如下的語句for (int i = 0; i < 10; i++){if (i == 5)j = 5;},什麼都寫在一行,你怎麼在j=5前面插入斷點
- 在一個1000次的循環體内部設定斷點,你希望當循環進行到900次後中斷,怎麼才能做到呢?
- 你有一個表達式在上面循環的某一次發生了變化,你想知道是哪一次,在哪個地方,怎麼才能做到?
- 你希望你的斷點在被命中100次後,每命中三次中斷一次,比如第103,第106,第109怎樣做?
- 你有在調試一個服務程式,希望在其内部打上了斷點,可是,由于這是一個公用的服務你不希望其他通路這個服務的程式被你的調試所幹擾,你想 怎麼辦?
- 怎樣知道2個斷點中斷的時間間隔
這兩個問題最簡單,我在一個例子裡說明
例如如下循環
for(int i=0;i<1000;i++){doSomeThing......}
在循環的大括号上單擊右鍵,插入斷點,用這個方法,可以對付那些喜歡把語句寫在一行上的家夥,其實,随着.Net3.5中Linq的出現,我們肯定也會經常在在一行上寫複雜的表達式,這個時候用這種插入方法會比較管用
ok,現在我們來編輯這個斷點的條件,在斷點上右鍵單擊,選擇如圖菜單項
在彈出的視窗中可以設定斷點命中的條件i==900
注意我是在調試C#代碼,預設的條件語句文法是C#,如果你想切換,那就需要用Ctrl- B,來插入斷點,并在彈出視窗中選擇語言
通過這樣設定條件斷點,我們就可以解決我們的問題1,2了
問題3
你有一個表達式在上面循環的某一次發生了變化,你想知道是哪一次,在哪個地方,怎麼才能做到?
同樣通過設定條件斷點我們還可以解決我們的問題3,對表達式變化的跟蹤
string user="yizhu2000"
for(int i=0;i<10000;i++){
DoSomething1()
.......
DoSomethingN()
}
當循環執行完畢時我們發現user變成了"smart_boy",你不知道這個值是在第幾次循環的時候變化的,那麼你是不是會選擇打上斷點,一次一次中斷,來檢視呢?當然不用
在循環體結束的位置我們設定一個斷點,打開條件編輯視窗(打開方法同上),設定表達式為 user,勾選下面的HasChanged,也就是說,你告訴斷點,當user的值發生變化時才觸發
(注意:第一次執行到斷點的時候,程式一定會中斷,并計算這時表達式的值,是以,所謂發生變化,指的是以後執行到斷點是表達式的值和第一次執行到斷點時表達式的值的比較)
問題4
你希望你的斷點在被命中100次後,每命中三次中斷一次,比如第103,第106,第109怎樣做?
如何讓斷點在指定的命中次數或者大于某個次數時觸發呢?方法是設定幾個斷點的 HitCount,右鍵單擊斷點,在彈出菜單中選擇Hit Count,會彈出如下視窗
在"when the break point is hit"下拉清單裡,我們可以看到四個選項
break always:總是中斷
break when the hit count is equal to:等于某次數時中斷
beak when the hit count is a multpile of:當次數是某數的倍數時中斷
break when the hit count is greater than or equal to:當大于等于某數時中斷
問題5
你有在調試一個服務程式,希望在其内部打上了斷點,可是,由于這是一個公用的服務你不希望其他通路這個服務的程式被你的調試所幹擾,你想怎麼辦?
前面4個問題都已經解決了,第5個問題的解決方法是利用斷點的Filter功能,比如我希望斷點隻有被機器名為yizhu的機器通路才能觸發,我可以這樣設定
當其他機器通路程式的時候,斷點将不會觸發,這樣做的優點是通過設定機器名,我們可以讓其他機器通路的時候感覺不到斷點的存在,除此之外我們可以設定機器名,程序号,程序名,線程号,線程名作為filter,而且還可以把他們組合起來,比如我希望通過當機器yizhu的dllhost程序調用時才觸發,那麼問題就可以設定為MachineName="yizhu"&ProcessName="dllhost"
問題6 怎樣知道2個斷點中斷的時間間隔
現在我們來解決第6個問題:
在程式性能調試的時候,我們經常需要知道某段代碼的執行效率,一般來說,我們可以在程式中加入時間點,通過時間點相減來取得時間間隔,這種方法有個顯而易見的缺點就是需要修改程式,想要不修改程式,就需要借助一些工具,那麼有沒有什麼方法可以聲明式的插入時間點,并計算值呢?其實斷點完全可以做到
在給出方法前,我們來看看斷點的另外一個設定項,When Hit,這個選項可以讓我們在命中斷點後做一些事情,包括輸出一些内容,或者調用宏,比如輸出一個程式中變量的值
我們輸出了變量user的值,下面Continue Execution表示程式不會中斷,輸出後繼續執行,注意表達式需要用{}括起來,,其他的部分會被作為字元串輸出。設定WhenHit後斷點變成了方形(看厭了圓斷點,我還挺喜歡這個方家夥的)
在output中檢視輸出結果,如下:
既然可以計算表達式,我們的第一個最簡方案就出來了,也就是在程式執行到斷點的時候,輸出 DateTime.Now,這樣當然是可行的,但是我們需要的是時間間隔,是以我們還需要自己來算個減法,還是挺麻煩的,怎麼樣才能讓程式自己輸出時間間隔呢?有一個想法是這樣的,我們在上一個斷點聲明一個時間變量,然後在下面的斷點裡用DataTime.Now減去這個變量,即
斷點一的條件:{DateTime _t=DateTime.Now;}
斷點二的條件:{DateTime.Now-t;}
看起來不錯,但是實際運作時就有問題了,讓我們看看輸出吧
上面高亮的部分說,變量申明隻能在immediate window中進行,是以斷點一的變量沒有申明成功,關于immediatewindow,我們以後會涉獵到,反正就是說想在表達式裡申明變量,沒門,死路一條.那麼我們怎麼才能不申明變量又時間點呢?
這時我想起了Thread.SetData 方法,這個方法可以往目前線程專門提供的空間中插入一些資料,并且可以通過GetData得到資料,具體細節參考
http://msdn2.microsoft.com/zh-cn/library/system.threading.thread.setdata(VS.80).aspx
于是方案就有了,在第一個斷點處把時間放入Thread的DataSlot,然後第二個斷點取出來相減
斷點一的條件: {Thread.SetData(Thread.GetNamedDataSlot("ExecutionTime"),DateTime.Now);}
斷點二的條件: {DateTime.Now-(DateTime)System.Threading.Thread.GetData(System.Threading.Thread.GetNamedDataSlot("ExecutionTime"));}
看看輸出效果
我們的目的已經達到了,output中成功的輸出了時間間隔,當然,還不是很完善,首先,這個方法限于兩個斷點,你想多打幾個斷點,測試兩兩間的間隔還是比較麻煩.測量精度也可以提高,大家有興趣可以自己研究這個方法的擴充