將(jiang)不(bu)確定變(bian)為確定~程序(xu)是否真的Dispose了
首先將來說(shuo)一下Dispose是什么東西(xi)吧,對于我們使用(yong)非托管的(de)資(zi)源時,需要(yao)自己去實現(xian)Dispose這個方法,它(ta)的(de)含義就是釋放使用(yong)的(de)內存空間。
例如Stream這(zhe)個類型(xing),它(ta)就(jiu)是一個非托管類型(xing),它(ta)會實現一個IDisposable接口(kou),來(lai)實現Dispose方法
像TransactionScope,.net事務(wu),它也是(shi)一個非托(tuo)管的,也就(jiu)是(shi)說,我們(men)在使用完事務(wu)后(hou),需要自己去進(jin)行Dispose()操作,下面問(wen)題(ti)就(jiu)來了,這個Dispose寫(xie)在哪里合適(shi)呢(ni)?
注意看這段代碼:
using (TransactionScope trans = new TransactionScope()) { try { this.Update(order); new WebAccountRecordsRepository().Insert(new WebAccountRecords { }); new WebAccountBalancesRepository().Update(new WebAccountBalances { }); } catch (Exception e) { // vm.AddItem(e.Message); throw; } finally {
trans.Dispose();
}
}
這是(shi)(shi)非常標(biao)準的(de)寫(xie)到,完(wan)成(cheng)一(yi)個(ge)訂單(dan)處理的(de)過程,它將處理訂單(dan),網站支付明細及(ji)網站總(zong)余額寫(xie)在了(le)一(yi)個(ge)事務里,這當然是(shi)(shi)沒有問題的(de),注(zhu)意看Dispose的(de)位置,寫(xie)在了(le)finally{}里,這也是(shi)(shi)對的(de),當try{}完(wan)成(cheng)后,將會(hui)執(zhi)行finally片斷(duan),但注(zhu)意catch{}段,它進行所有異常的(de)捕捉(zhuo),并(bing)進行拋出,好了(le),如(ru)果這個(ge)try{}段出現(xian)了(le)異常,那finally{}段是(shi)(shi)否會(hui)執(zhi)行嗎(ma)?也就是(shi)(shi)dispose是(shi)(shi)否會(hui)被執(zhi)行呢(ni)?
經過我的(de)測試,它有執行,但由于你使用(yong)了(le)(le)throw,所(suo)以(yi)網頁直接(jie)黃屏了(le)(le),所(suo)以(yi),最好把catch段進行處(chu)理,你可以(yi)去把異常寫到日(ri)志里,但有一點要(yao)注意(yi),finally{}塊里不要(yao)寫可能會(hui)出現異常的(de)代(dai)碼,否則,會(hui)使你的(de)事務資源永遠(yuan)得到不釋放!
例如:
using (TransactionScope trans = new TransactionScope()) { try { this.Update(order); new WebAccountRecordsRepository().Insert(new WebAccountRecords { }); new WebAccountBalancesRepository().Update(new WebAccountBalances { }); } catch (Exception e) { // vm.AddItem(e.Message); throw; } finally { Insert(list.First().id); //如果list集(ji)合為空,那(nei)這行會出現異(yi)常(chang),導(dao)致它下面(mian)的代(dai)碼將不(bu)能被執行 trans.Dispose(); } }
當然,這一般是由于編(bian)程(cheng)習(xi)慣(guan)引起(qi)的,大家以后注意就行(xing)了,在(zai)finally里(li)釋(shi)放(fang)資源時,應(ying)該考(kao)慮異常進(jin)行(xing)一些(xie)必要的判斷。
如果(guo)非要寫在finally里,如果(guo)你的對象不能確定是否會(hui)發生(sheng)異常,那就try,catch吧,看代碼:
finally
{
try {
Insert(list.First().id); //如果list集合(he)為空,那這行會出現異常,導致(zhi)它(ta)下面的代碼將不能被執行
}
catch (Exception e)
{
throw;
}
finally
{
trans.Dispose();
}
}
這樣,trans.Dispose()也(ye)是(shi)會(hui)被執行的,也(ye)就是(shi)說,對于同一(yi)個try,catch,finally來說,finally是(shi)永遠都會(hui)被執行的。