事件的多重觸發與移除

避免同一個事件多次重覆觸發與移除,讓事件觸發在對的時間.

  或許有些人會因為功能上的需求,所以在一些事件(例如TextChanged)的處理上是使用手動新增,但有時一個不小心,就可能會造成事件的重覆觸發多次,或者當我們在某些狀況下,其實事件是不用觸發的,減少不必要的動作,這時就要把它給停止.

  首先瞭解到一個問題,一般我們的事件都是放在InitializeComponent()裡面,textBoxTextChanged事件為例,在裡面就可以看到this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged),可是有些狀況我們會是後期才會加入,並不會放在InitializeComponent()裡面,這時就要注意到一個狀況,如果重覆執行this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged) ,就會造成同一事件多次觸發的情況.

 

舉例來說 :

 

 

private void Form1_Load(object sender, EventArgs e)

{

    this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged);

    this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged);

}




private void textBox3_TextChanged(object sender, EventArgs e)

{

    MessageBox.Show(“Hello”);

}

 

  我在Form Load的事件中,故意加了兩次TextChanged事件,當我執行去修改TextBox的值時,畫面就會跳了兩次HelloMessageBox出來,也就是說,我加了幾次,它就會觸發幾次,其實會發現這個問題,也是之前遇到的一個經驗,使用者回報說,有隻作業很奇怪,操作愈久,它的速度愈慢,當下只有覺得奇怪,沒想到程式碼裡的問題,但後來去看了一下內容才發現,有個function會新增TextChanged事件,重點是它不只被呼叫一次,所以使用者操作愈多次,這個TextChanged的事件就會觸發愈多,當下就加了一行Code把這個事件給移除.

  即然提到事件的移除,接下來要提的就是如何把事件給移除掉,其實反應快的人可能已經發現了,如果+=是新增事件,那麼-=就會是移除事件,答案沒錯,就是這樣移除, this.textBox3.TextChanged -= new System.EventHandler(this.textBox3_TextChanged),但或許會有個疑問,之前我可能加了三次事件,那麼我是否也要移三次才能移完?答案是不用的,只要移一次,就會把之前的全移除.

 

比如說 :

 

private void Form1_Load(object sender, EventArgs e)

{

    this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged);

    this.textBox3.TextChanged += new System.EventHandler(this.textBox3_TextChanged);

}




private void textBox3_TextChanged(object sender, EventArgs e)

{

    MessageBox.Show(“Hello”);

    this.textBox3.TextChanged -= new System.EventHandler(this.textBox3_TextChanged);

}

  第一次修改TextBox,還會觸發兩次MessageBox出來,但當我再去修改TextBox的值時,MessageBox就不會再跳出來了.

 

  像這種技巧我會運用在某些情況,比如說畫面上有兩個TextBox控制項,當使用者在其中一欄輸入代號,就會回資料庫查詢取回此代號的名稱,並顯示於另一個TextBox,這是很常見的一種運用,但如果是使用者使用查詢功能,一次取回此表單上的所有資訊,也就是代號之名稱時,並不需要再額外的去觸發事件回資料庫取值,造成不必要的Request\Response,增加資料庫及網路與系統的負擔,所以這時就可以先把事件給移除”,等畫面更新完,再把事件給新增回來即可.

 

  之前有個表單上有數十個TextBox有這種情況,當輸入值時,會觸發事件,回資料庫取資料,由於輸入時是一格一格輸入,就沒什麼感覺,但如果只是單純的載入這張表單,就會跑很久,其實一開始就把所有的資訊取回了,只是各事件在資料異動時又觸發,又回資料庫取了一次資料,才會導致這個表單的效能不好.後來就在這事件的處理上做了調整,效能就大為的提升.

 

參考 :

MSDN 事件範例

HOW TO:訂閱及取消訂閱事件 (C# 程式設計手冊)