This article is reproduced from:
http://www.cnblogs.com/yhlx125/archive/2011/11/22/2258543.html#2269154 my blog.
Http://www.cnblogs.com/tendzzss/archive/2011/11/11/2245627.html
AE's COM object needs to be released, otherwise it may lock up some basic devices (such as MDB files, etc.), here is the case of the AE lock MDB.
The release method is generally, marshal.releasecomobject or marshal.finalreleasecomobject
But when to release COM objects, you need to understand how dotnet interacts with com: the runtime callable Wrapper (RCW).
This reference count is incremented each time a COM interface pointer is mapped to the runtime callable wrapper. This is a sentence in the Marshal.ReleaseComObject method description in MSDN. What does that mean, what kind of operation causes a COM interface pointer to be mapped to a runtime callable wrapper. Did a simple experiment, opened a workspace, and opened a featureclass, Use the method marshal.releasecomobject to free COM, view the reference count (you do not know how to view the reference count, only through the Marshal.ReleaseComObject method), to determine whether the COM interface pointers are executed to be called to runtime callable package operations.
Case one: New declaration of a workspace local variable, assigning the original workspace value to the new variable, releasing the workspace, and viewing the workspace reference count
1 iworkspacefactory wsf = new Accessworkspacefactoryclass (); 2 iworkspace ws = WSF. Openfromfile (Mdbpath, 0); 3 ifeatureclass FLS = ((ifeatureworkspace) WS). Openfeatureclass (Featureclassname); 4 iworkspace ws1 = ws;5 int i = Marshal.ReleaseComObject (WS); 6 7//i has a value of 0.
Scenario two: New declaration of a workspace local variable, assigning a value to a new variable through the Idataset.workspace property, releasing the workspace, and viewing the workspace reference count
1 iworkspacefactory wsf = new Accessworkspacefactoryclass (); 2 iworkspace ws = WSF. Openfromfile (Mdbpath, 0); 3 ifeatureclass FLS = ((ifeatureworkspace) WS). Openfeatureclass (Featureclassname); 4 Iworkspace ws1 = ((Idataset) FLS). workspace;5 int i = Marshal.ReleaseComObject (WS); 6//i has a value of 1.
I ventured to conclude (possibly wrong): mapping a COM interface pointer to a runtime callable wrapper operation occurs when a COM object method is called and the return value is returned.
Situation three: Open Featureclass in a method, do not release workspace, new declaration of a workspace local variable, Take responsibility for the new variable through the Idataset.workspace property, release workspace, view workspace reference count
1 Private ifeatureclass GETFCLSS (string path, String featureclassname) 2 {3 iworkspacefactory wsf = new Accesswor Kspacefactoryclass (); 4 iworkspace ws = WSF. Openfromfile (path, 0); 5 return ((Ifeatureworkspace) WS). Openfeatureclass (Featureclassname); 6 } 7 Ifeatureclass FLS = GETFCLSS (Mdbpath, featureclassname); 8 iworkspace ws = ((Idataset) FLS). Workspace; 9 int i = Marshal.ReleaseComObject (WS), and the value of//i is 1.
Situation four: Similar to the situation three, the difference is called the Gc.collect method
1 Ifeatureclass FLS = GETFCLSS (Mdbpath, Featureclassname); 2 GC. Collect (); 3 iworkspace ws = ((Idataset) FLS). workspace;4 int i = Marshal.ReleaseComObject (WS), 5 6//i has a value of 0.
Compare case four, it can be concluded that when the COM object is released in the Dotnet mapping object, the reference count will be reduced by one
Scenario Five: Call condition three to get Featureclass method, release get Featureclass, delete mdb file
1 Ifeatureclass FLS = GETFCLSS (Mdbpath, Featureclassname); 2 Marshal.ReleaseComObject (FLS); 3 File.delete (MdbPath);
Get "File" ... "is being used by another process, so the process cannot access the file. "Exception.
Situation Six: Modify the Getfclss method, release the Worksapce within the method, and then operate as the case five
1 Private ifeatureclass GETFCLSS (string path, String featureclassname) 2 {3 iworkspacefactory wsf = new Accesswor Kspacefactoryclass (); 4 iworkspace ws = WSF. Openfromfile (path, 0); 5 Try 6 {7 return ((Ifeatureworkspace) WS). Openfeatureclass (Featureclassname); 8 } 9 finally10 { marshal.releasecomobject (ws); }13 }
You can then delete the file.
Situation Seven: Call condition six modified GETFCLSS, do not release featureclass, delete file directly
1 Ifeatureclass FLS = GETFCLSS (Mdbpath, Featureclassname); 2 file.delete (Mdbpath);
Get a situation like five exceptions.
Situation eight: Call situation six modified GETFCLSS, the new declaration of a workspace local variable, through the Idataset.workspace property to assign a value to the new variable.
1 Ifeatureclass FLS = GETFCLSS (Mdbpath, Featureclassname); 2 iworkspace ws = ((Idataset) FLS). Workspace;
The resulting WS is a property that can be viewed, and the released COM Object View property will be prompted as "the COM object is no longer available after it is separated from its base RCW." "Exception.
Situation Nine: Workspace open ifeatureclass2 times
1 iworkspacefactory wsf = new Accessworkspacefactoryclass (); 2 iworkspace ws = WSF. Openfromfile (Mdbpath, 0); 3 ifeatureclass fcls= ((ifeatureworkspace) WS). Openfeatureclass (Featureclassname), 4 Ifeatureclass fcls1 = ((ifeatureworkspace) WS). Openfeatureclass (featureclassname); 5
So what happens to the properties that access the properties of the COM object?
Scenario Ten: Create the GetDataSet method, as with the new GETFCLSS, just return the Idataset, Access Idataset.workspace, then access IDataset.Workspace.PathName, Release Workspace, view reference count
1 Private idataset GetDataSet (string path, String featureclassname) 2 {3 iworkspacefactory wsf = new Accessworksp Acefactoryclass (); 4 iworkspace ws = WSF. Openfromfile (path, 0); 5 Try 6 {7 return ((Ifeatureworkspace) WS). Openfeatureclass (Featureclassname) as Idataset; 8 } 9 finally10 { marshal.releasecomobject (ws); }13 }14 idataset ds = GetDataSet (Mdbpath, featureclassname); iworkspace ws = ds. Workspace;16 string s = ds. workspace.pathname;17 int i = Marshal.ReleaseComObject (WS), and the value of//i is 1.
Therefore, in order to avoid the release of some objects, it is best not to use the IDataset.Workspace.PathName.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////
. NET hosting is not a panacea, and some resources such as forms, files, bitmaps, and database connections need to be manually recycled.
Managed memory used by. NET, value types are stored on the stack, reference types are stored on the managed heap, and GC is responsible for garbage collection. COM objects use built-in memory and therefore cannot be managed and need to manually free up memory. But what about the memory management mechanism of COM? the. NET environment calls COM components, and how does garbage collection for COM objects work, and what are the general principles? I don't know anything about that.
So I posted the help on the ArcGIS Engine forum and no one answered. Now the problem to be re-organized, sent to the blog Park, hoping to get answers. Whether it's yourself or someone else's help. Also record the process. A total of three posts were issued, as follows:
How should the garbage collection problem of COM objects be carried out in the two development of 1.AE?
AE is a two-time development, often overlooked garbage collection problem, AE is a COM object, garbage collection problem should be how to do? When is the COM object in the generic for loop released, or is it automatically released? Other situations should be aware of what kind of code, QU objects need garbage collection?
1 for (int i = 1; i < 2500; i++) 2 {3 iqueryfilter qu = New queryfilterclass ();//com object QueryFilterClass4 qu. Whereclause = @ "area =" + i.tostring (), 5 ifeaturecursor featcursor = Featclass.search (Qu, true);//com Object 6 //Use T He feature cursor as Required7 System.Runtime.InteropServices.Marshal.ReleaseComObject (featcursor); 8 }
1 try{2 ystem. Runtime.InteropServices.Marshal.ReleaseComObject (Ofield); 3//feel there are some problems here, its ofield in front new many times, now in the final cleanup, do not know whether it really played a full role? 4 System.Runtime.InteropServices.Marshal.ReleaseComObject (ofields); 5 System.Runtime.InteropServices.Marshal.ReleaseComObject (Ofieldsedit); 6 System.Runtime.InteropServices.Marshal.ReleaseComObject (Ofieldedit); 7 System.Runtime.InteropServices.Marshal.ReleaseComObject (PName); 8 System.Runtime.InteropServices.Marshal.ReleaseComObject (PWSF); 9 System.Runtime.InteropServices.Marshal.ReleaseComObject (pwsname); 10 System.Runtime.InteropServices.Marshal.ReleaseComObject (PMEMORYWS); 11 System.Runtime.InteropServices.Marshal.ReleaseComObject (Ofeatureclass),}13 catch14 {}15 GC. Collect ();
One example of the cleanup is System.Runtime.InteropServices.Marshal.ReleaseComObject (pfeaturecursor);
Q: To fully free the COM object underlying an RCW from memory at a deterministic point, it's possible to use the Releaseco Mobject method on the Marshal class, which are part of the System.Runtime.InteropServices namespace in the. NET Framework. Calling ReleaseComObject would decrease the reference count held on an RCW; Once the reference count on the RCW reaches zero (which could require repeated calls to ReleaseComObject), the RCW is marked For garbage collection. If No other COM objects hold a reference to the underlying COM object at that point, the COM runtime would also clear up th E COM object itself. Does this sentence of the ArcGIS Engine Help document explain the previous content? Although the COM object new Fieldclass object that Ofield points to is not purged every time in the loop, the number of references is already 0, so COM automatically frees the
PostScript: iqueryfilter qu = New queryfilterclass (), scope in the For loop, of course, is not accessible elsewhere, but the memory management is exactly what is going on or not very clear!
Later I thought:
The statement in the For loop iqueryfilter qu = New queryfilterclass (), although not accessible outside the scope of the For loop, but not equal to the memory being freed:
81 rows of Ifield Ofield = new Fieldclass ();//com Object
97 lines, 114 rows of Ofield = new Fieldclass ();//com Object
The system is called in line 156. Runtime.InteropServices.Marshal.ReleaseComObject (ofield), releasing COM objects, and COM object references minus 1, at which point the Ofield refers to 114 rows, new Fieldclass () Generated COM object, at this time 81 lines new and 97 line new COM object is not into the garbage memory?
There is also the Arcscene load layer, the repeated loading of memory will continue to grow. There seems to be some problems in dealing with it.
Q: Previously asked in the post bar on the collection of COM objects, now makes me feel more confused! I did a test, there is only one form in the program, the form layout a mapcontrol and Lisencecontrol and a botton button, the event code of the button is as follows:
1 private void Btnaddmap_click (object sender, EventArgs e) 2 {3 imapdocument Pmapdoc = new Mapdocumentclass ();//m Apdocumentclass is COM object 4 pmapdoc.open ("d:\\ demo data \ \ topic [Url=file://\\untitled.mxd]\\untitled.mxd[/url]", "" "); 5 IMAP PMAP = pmapdoc.get_map (0);//interface that returns COM object Mapclass IMap 6 axmapcontrol1.map = pMap; 7 Marshal.ReleaseComObject (Pmapdoc); (1) 8 marshal.releasecomobject (PMAP); (2) 9 GC. Collect (); (3) Ten Axmapcontrol1.refresh ();
The
(1) (2) (3) code does the following combinations, the class A three lines are not added, B is added (1) (2), C is added (3), D adds (1) (2) (3) sentence code. Repeat the click button for each combination so that the MAP is loaded repeatedly, with Mapdocumentclass and Pmapdoc.get_map (0) generating new COM objects each time, and the first load of memory growth is more understandable. Class A loaded to about 21 times, the program pop-up error (1), b do not eject errors, click 40 No error, at this time the memory is constantly rising; C memory does not grow so fast in the B, the time of the click of about 20 times seems basically stable; My data is mainly some of the tin and some elements in a geodatabase (Figure 2), the entire data set size of about 5M, the map document 749K;
So it seems that only new COM objects, as long as no further reference should be released better!
Q: It is still the previous program that returns the number of references n,m after the current COM object is released by the following two sentences.
int n= marshal.releasecomobject (pmapdoc);
int m = Marshal.ReleaseComObject (PACT);
is called once, the return value is 0:1,
Add a sentence m= marshal.releasecomobject (PMAP); The return value is 0:0
Interface variable assignment and interface jumps do not affect execution results. Which means that neither of them affects the reference count?
1 IMap pMap2 = pMap; 2 Iactiveview pAct = PMap as Iactiveview, (add separately) 3 private void Btnaddmap_click (object sen Der, EventArgs E) 4 {5 Imapdocument Pmapdoc = new Mapdocumentclass ();//mapdocumentclass is COM object 6 Pmapdoc.open ("d:\\ Red Rock demo data \ \ Geology topic [Url=file://\\untitled.mxd]\\untitled.mxd[/url]", "" "); 7 IMAP PMAP = PMAPDOC.GET_MAP (0);//interface that returns COM object Mapclass IMap 8//imap pMap2 = PMap; 9//iactiveview pAct = PMap as iactiveview;10 axmapcontrol1.map = pmap;11 int n= Marsha L.releasecomobject (pmapdoc); int m= marshal.releasecomobject (pMap);//int m = marshal.releasecom Object (PACT),//int m= marshal.releasecomobject (PMAP2), +//m = Marshal.ReleaseComObject (PMAP2); GC. Collect (); Axmapcontrol1.refresh (); MessageBox.Show (n.tostring () + ":" + m.tostring ()); 19 }
Use the following code: Imapdocument pmapdoc = new Mapdocumentclass ();
Change the code in the button to such that the return value 0:0:1,i value is minus 1 for the Mapdocumentclass object count that was defined for the first time
1 pmapdoc.open ("d:\\ demo data \ \ Geology topic [Url=file://\\untitled.mxd]\\untitled.mxd[/url]", "" "); 2 int i = Marshal.ReleaseComObject (Pmapdoc); 3 Pmapdoc = new Mapdocumentclass (); 4 Pmapdoc.open ("d:\\ demo data [url=file://\\data\\position.mxd]\\data\\ Position.mxd[/url] "," "); 5 IMap pMap = pmapdoc.get_map (0), 6 axmapcontrol1.map = PMAP; 7 int n= marshal.releasecomobject (pmapdoc); 8 int m = Marshal.ReleaseComObject (PMAP); 9 GC. Collect (); Axmapcontrol1.refresh (); MessageBox.Show ( i.tostring () + ":" +n.tostring () + ":" + m.tostring ());
The above tests the repeated loading of the map, some of the symptoms that appear. Later found that he neglected the Colse method of Mapdocument. Does this method release the file resources?
Continue to test the following code:
1 private void Btnaddmap_click (object sender, EventArgs e) 2 {3 imapdocument Pmapdoc = new Mapdocumentclass (); 4< C4/>pmapdoc.open ("d:\\ demo data \ \ topic [Url=file://\\untitled.mxd]\\untitled.mxd]\\untitled.mxd]\\untitled.mxd[/url]", " "); 5 IMap pMap = pmapdoc.get_map (0), 6 pmapdoc.close (), 7 axmapcontrol1.map = PMAP; 8 int n = marshal.releas Ecomobject (Pmapdoc); 9 int m = Marshal.ReleaseComObject (PMAP); Axmapcontrol1.refresh ();
The memory is still rising, but there are no resource-poor errors. But the explanation of the help document is to reset the Mapdocument object.
1. Test the following code:
Imapdocument Pmapdoc = new Mapdocumentclass (); Pmapdoc.open ("d:\\ demo data \ \ topic [Url=file://\\untitled.mxd]\\untitled.mxd[/url]", "" "); IMap pMap = pmapdoc.get_map (0); Pmapdoc.close (); int n = marshal.releasecomobject (pmapdoc); int m = Marshal.ReleaseComObject (PMAP); MessageBox.Show (n.tostring () + ":" + m.tostring ());
The return value is: 0:0, you can see that IMAP PMAP = Pmapdoc.get_map (0), and added a reference count for the Map at one time.
2. The following code:
1 imapdocument pmapdoc = new Mapdocumentclass (); 2 pmapdoc.open ("d:\\ demo data \ \ Geology topic \\Untitled.mxd", ""); 3 IMap pMap = pmapdoc.get_map (0), 4 pmapdoc.close (), 5 axmapcontrol1.map = pmap;6 int n = Marshal.ReleaseComObject (Pmapdoc); 7 int m = Marshal.ReleaseComObject (PMAP); 8 MessageBox.Show (n.tostring () + ":" + m.tostring ());
The return value is 0:1, which shows axmapcontrol1.map = PMap; Adds a reference count to the Map object one time.
3. The following code:
1 imapdocument pmapdoc = new Mapdocumentclass (); 2 pmapdoc.open ("d:\\ demo data \ \ Geology topic [url=file://\\untitled.mxd]\ \untitled.mxd[/url] "," "); 3 IMap pMap = pmapdoc.get_map (0), 4 pmapdoc.close (), 5 axmapcontrol1.map = PMAP; 6 int n = marshal.releas Ecomobject (Pmapdoc);(1) 7 int m = marshal.releasecomobject (PMAP);(2) 8 m = Marshal.ReleaseComObject (PMAP); (2) 9 GC. Collect ();(3) Axmapcontrol1.refresh ();
for (1) (2) (2) (3) performing combinations, (1) (2), (1) (2) (2), (1) (2) (2) (3) Three combinations, found that the last effect is obvious, the memory does not continue to grow and will fluctuate. But the first two types of memory will continue to grow. Is the effect of forcing GC cleanup so obvious? Does the resulting memory growth not be due to COM objects, MXD files, but managed memory? Hope the Warrior explains.
Http://www.cnblogs.com/yhlx125/archive/2011/12/13/2286108.html
At the end of the blog post, there was a problem: Gc.collect () significantly freed up memory, does forcing GC cleanup be so obvious? Does the resulting memory growth not be due to COM objects, MXD files, but managed memory?
This led to the idea that Mapclass, Mapdocumentclass objects are. NET managed objects, not COM objects. Is that the case?
Imapdocument Pmapdoc = new Mapdocumentclass ();
int n = marshal.releasecomobject (Pmapdoc);
Indeed, the return value of 0 indicates that the COM object was disposed correctly. If the execution of the next paragraph of code, the 2nd sentence error, description. NET object cannot be manipulated using the Marshal.ReleaseComObject () method.
1 a pa = new A (), 2 int m = Marshal.ReleaseComObject (PA), 3 MessageBox.Show (m.tostring ()); 4 5 Class A 6 { 7 int A; 8 public int A1 9 { Ten get {return A;} One set {a = value;} 13}
Then find the relevant information: Learn the following topics:
1. COM Interoperability
2. Primary Interop Assemblies (PIAs, primary interop assembly), Http://msdn.microsoft.com/zh-cn/library/aax7sdch.aspx
The primary interop assembly is a unique assembly provided by the vendor. It contains the type definition (as metadata) of a type implemented with COM. There can be only one primary interop assembly, and the Assembly must be signed with a strong name by the publisher of the COM type library. A primary interop assembly can wrap multiple versions of the same type library.
If the COM type library that is imported as an assembly is not signed by the publisher of the original type library, the type library cannot be used as the primary interop assembly. Only the publisher of the type library can produce a true primary interop assembly. The assembly becomes the formal type definition unit that is used to interoperate with the underlying COM type.
Publishers of COM components generate primary interop assemblies and publish them to developers for use in. NET Framework applications. For publishers, this section provides information about generating primary interop assemblies. For developers, this section describes how to program with primary interop assemblies.
3. com Packaging: Http://msdn.microsoft.com/zh-cn/library/5dxz80y2.aspx
COM wrapper (COM Wrapper)
The runtime provides wrapper classes that allow managed and unmanaged clients to think that they are calling objects in their respective environments. Whenever a managed client invokes a method on a COM object, the runtime creates a runtime callable wrapper (RCW). One of the functions of the RCW is to extract the differences between managed and unmanaged reference mechanisms. The runtime also creates a COM callable wrapper (CCW) to reverse this process, enabling COM clients to seamlessly call methods on. NET objects. As shown, the nature of the calling code determines the wrapper class that is created at run time.
Using the RCW,. NET client program is available. NET objects instead of COM components, you do not need to handle COM attributes, which are handled by the wrapper. The RCW hides the IUnknown interface and the IDispatch interface and handles the number of references to COM objects. (C # Advanced Programming version sixth, page 686)
So the question is clear, IMap pMap = new Mapclass (); This code uses the PIAs representation provided by ESRI, PIAs contains the type definition (as metadata) of the type implemented by COM. The Mapclass object itself is a. NET object that implements a wrapper over the COM object map, which can be thought of as passing a reference to the Map object. So at the end of the question, calling Gc.collect () significantly freed up memory because the wrapper object was freed Mapclass, and the wrapper RCW object is a COM-to. NET Bridge, (can data marshaling be considered a copy of the data?). ) Marshal.ReleaseComObject (Pmapdoc), releasing the COM object but not releasing the managed RCW, so the memory waits for the managed runtime to be freed.
(The standard RCW or CCW generated at run time will provide sufficient marshaling for calls that span the boundaries between the COM and. NET Framework.) )
4. Marshaling Http://msdn.microsoft.com/zh-cn/library/9f9f3yxf.aspx
Category: AE development
Problems with. NET Development AE releasing COM objects