C#中閉包的陷阱

來源:互聯網
上載者:User

標籤:

在最近的項目中,我封裝一個非同步執行程式的組件。這個組件的功能就是在執行一些耗時的後台操作(比如連資料庫讀取資料,或者後台進行一些統計計算)的時候不阻塞UI,再彈一個轉圈圈的動畫告訴使用者正在執行後台操作。方法包含三個參數,其中前兩個是委託類型,分別是耗時操作的doWork和操作完成後的回調callBack。第三個參數就是彈出的等待動畫旁邊的提示訊息,類似於“正在尋找資料,請稍後。。。"之類的文本,由調用方設定。方法代碼大概長下面這個樣子:

 public static void Run(Action doWorker, Action callBack, string message)        {           //todo:method body        }

因為這個組件我設計成不依賴於任何其他表單,也就是說這個組件是一個獨立的window,而不是作為一個控制項插入到其他表單。在其他任何window裡調用都是直接調用這個靜態方法即可在調用的window前彈出一個等待視窗,並且調用的地方也沒有阻塞。那麼問題來了,在這個方法裡我怎麼才知道是哪個window或者Control在調用呢?我採用的方法是使用doWorker的Target屬性來擷取當前調用的window,把它賦給組件的Owner,再把組件的啟動位置設為Owner的中央即可。代碼如下:

this.Owner = doWorker.Target as Window;
if(this.Owner == null)
{
  this.Owner = Window.GetWindow(doWorker.Target as Control);
}this.Show();

嗯,大功告成。run起來很順暢,直到一段代碼的出現。那是下面這樣一段代碼:

var orderTable = grd_Order.DataSource as DataTable;if(orderTable == null) return;MsgWindow.Run(()=>{        DbHepler.Update(orderTable);    },null,"正在儲存資料,請稍後!);

MsgWindow正是我封裝的組件的類名。不知道為什麼,這段代碼調用時鐘出錯,異常出在Run方法中的這句代碼:this.Owner = Window.GetWindow(Traget as Control);

因為調用組件的也許可能不是Window而是一個UserControl,而這句代碼正是針對調用方是UserControl的。報的異常是說Window.GetWindow的參數不能為null,也就是說doWorker.Target as Control失敗了,doWorker.Target根本不是一個Window,也不是一個Control。這怎麼可能?!!代碼明明就是寫在一個自訂的Control。而且這個Control中還有另外一處也是調用的Run方法,參數都差不多,那裡就沒問題,運行得很順暢。為什麼就這個調用失敗了呢?

經過跟蹤調試,發現原來問題出在調用的地方。調的地方傳第一個參數doWorker的時候,使用了閉包。在這個匿名方法中引用了外部變數orderTable。我想起之前看過的關於C#閉包的實現原理,其實是將引用的外部對象封裝在一個匿名的類裡了,引用的外部對象作為這個匿名類的一個成員。在這裡,編譯的時候C#編譯器默默的為orderTable變數產生了一個匿名的類,orderTable作為這個匿名類的成員而儲存了下來。要不是這麼處理的話,還沒來得及執行匿名方法,orderTable就已經超出了範圍而不可訪問了。

找到問題根源後,解決方案也就呼之欲出了。其實這雷根本用不著閉包,將orderTable放在匿名方法裡面即可解決。如下:

if(orderTable == null) return;MsgWindow.Run(()=>{        var orderTable = grd_Order.DataSource as DataTable;        DbHepler.Update(orderTable);    },null,"正在儲存資料,請稍後!);    

 

C#中閉包的陷阱

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.