嘗試讀取或寫入受保護的記憶體。這通常指示其他記憶體已損壞

來源:互聯網
上載者:User
NET+AE開發中常見幾種非託管對象的釋放轉自:http://hi.baidu.com/murphy1314

.NET+AE開發中常見幾種非託管對象的釋放

我們知道.Net中對於記憶體的管理有兩種方式,一種是託管對象管理,另一種是非託管對象管理。而我們通常理解的記憶體管理就是GC(垃圾收集),雖然GC通過對託管堆的管理,可以使我們有機會從繁鎖的諸如記憶體流失之類的問題中解放出來,可以將精力專註於程式的邏輯上。但是將所有的事情都交給GC有時會損及程式的效率,嚴重的甚至會導致錯誤。

為什麼會出現這種情況呢?問題在於對非託管資源(檔案控制代碼)或者需要特別關照的對象(Bitmap)對象等,GC表現得就有點差強人意了(這句話或許說得並不正確,因為微軟設計GC的本意就是用來針對託管對象管理)。如何有效地利用GC來進行記憶體管理,如何對程式的效能進行最佳化不是本文討論的範圍。本文的要旨在於AE開發中如何來釋放非託管對象。

一、AOUninitialize.Shutdown.

很多時候我們都會遇到這種情況:在退出AE應用程式中,常常提示這樣的錯誤:“The instruction x
references memory at x. The memory could not be
read”。出現這種錯誤的原因主要在於COM對象(非託管對象)沒有釋放,在我們結束使用它的進程的時候,它阻止我們正常釋放它,它釋放的優先順序高於當前使用它的進程釋放的優先順序,也就是說進程釋放之前,必須先釋放掉它。

明白了上面的原理,那麼解決這一問題的方法便非常簡單,我們只需在應用程式退出之前調用ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown()方法即可釋放非託管對象了(9.2之前的版本AoUninitialize並不在ESRI.ArcGIS.ADF.COMSupport命名空間下,需注意)。

二、Marshal.ReleaseComObject

NET開發中,引用COM對象主要是通過RCW(Runtime Callable
Wrappers)機制來實現的(有點類似於代理模式)。對於COM對象的釋放,GC表現得有點無能為力,因此必須在程式中顯示釋放掉COM對象佔用的資源,否則將會出現一些意想不到的錯誤。比如重複地從Personal
GeoDataBase中開啟GeoDataBase Cursors而又沒有及時釋放,將會引發“No more tables can be
opened.”其它情形中,你可能會發現應用程式退出時,COM對象依然在記憶體中引用。比如StyleGallery如果沒有顯示釋放,在應用程式退出時就會引發錯誤。

1、Releasing StyleGallery:

private void MyFunction()
{
IStyleGallery styCls =
new StyleGalleryClass() as IStyleGallery;
// Use the StyleGalleryClass here
...
int refsLeft = 0;
do
{
    refsLeft =
Marshal.ReleaseComObject(styCls);
}
while (refsLeft >
0);
}
2、Releasing geodatabase cursors

for (int i = 1; i < 2500; i++)

{
      IQueryFilter qu = New
QueryFilterClass();
       qu.WhereClause = @"Area = " +
i.ToString();
      IFeatureCursor featCursor = featClass.Search(qu,
true);
      // Use the feature cursor as required
     
System.Runtime.InteropServices.Marshal.ReleaseComObject(featCursor);
}
3、Releasing
WebObject(ArcGIS Server)

private void doSomthing_Click(object sender,
System.EventArgs e)
{
using (WebObject webobj = new
WebObject())
{
    ServerConnection serverConn = new
ServerConnection("doug", true);
    IServerObjectManager som =
serverConn.ServerObjectManager;
    IServerContext ctx =
som.CreateServerContext("Yellowstone","MapServer");
    IMapServer mapsrv =
ctx.ServerObject as IMapServer;
    IMapServerObjects mapo = mapsrv as
IMapServerObjects;
    IMap map = mapo.get_Map(mapsrv.DefaultMapName);
   
IFeatureLayer flayer = map.get_Layer(0) as IFeatureLayer;
    IFeatureClass
fclass = flayer.FeatureClass;
    IFeatureCursor fcursor =
fclass.Search(null, true);
    webobj.ManageLifetime(fcursor);
   
IFeature f = null;
    while ((f = fcursor.NextFeature()) != null)
   
{
      // do something with the feature
    }
   
ctx.ReleaseContext();
}
}
三、什麼時候應該釋放非託管對象?

這個問題非常重要,當我們確信在釋放之後不再調用非託管對象資源時候,就可以調用System.Runtime.InteropServices.Marshal.ReleaseComObject()方法進行顯式釋放了,否則將會引發新的錯誤。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.