none
diff between Dynamic and NoDynamic RRS feed

  • Question

  • i have confuse about Microsoft.Office.Interop.Word reference in project, i have two project which all reference Microsoft.Office.Interop.Word.dll, and i sure the dll file is exactly the same one, the physical location in my folder is:C:\Program Files (x86)\Microsoft Visual Studio 11.0\Visual Studio Tools for Office\PIA\Office15\Microsoft.Office.Interop.Word.dll, but when i writing code in each project, i found the code is something different, for example:

    the code in project A:

    Word.Paragraphs ps = this.piaDocument.Paragraphs;
    foreach (Word.Paragraph p in ps) {
    	Word.Style style = (Word.Style)p.get_Style();  // return Object
    	// some other code
    }


    the code in project B:

    Word.Paragraphs ps = this.piaDocument.Paragraphs;
    foreach (Word.Paragraph p in ps) {
    	Word.Style style = p.get_Style();  // return dynamic
    	// some other code
    }


    because i can't posted picture in this forum, so i posted to skydriver.

     dynamic reference picture:

    https://pjkzua.dm2304.livefilestore.com/y2pV3szUQVJAdMxPw7FVWb8o6GjbLDv5YfCW1ZvtexpSuWaycZEf-ZPPmj91rgIX7wR5iBRpHAn7yNgxFbCcBPB3WZVyh4YRPHtqVAgbUB48Zw/Dynamic.png?psid=1

    NoDynamic reference picture:

    https://pjkzua.dm2301.livefilestore.com/y2p4IKLpPHM0kyXnjsahrZTptmStEwEgNRF7GaEzGv_8YaP7pnOPscfBiHUEgSMIyBamefHzJ7hRKq7AqyOwj4TpIDQK2ZPMlR9hCg9bEy-QNg/NoDynamic.png?psid=1

    i don't know why a same dll reference has so different behavior?  i should solve this problem because in my test the performance between than is a huge difference.

    thanks.


    • Edited by sendreams Saturday, December 7, 2013 8:06 AM
    Saturday, December 7, 2013 8:02 AM

Answers

All replies

  • i find this problem's reason is the "Embed Interop Type" setting in reference property which should be set to "false". and the different is not associate with performance.  i will check the code again.

    Saturday, December 7, 2013 8:29 AM
  • i found the really reason is the loop,  i use a document with 1429 Paragraphs and use the test below:

    Word.Paragraphs ps = this.piaDocument.Paragraphs;
    foreach (Word.Paragraph p in ps) {
    	Word.Style style = (Word.Style)p.get_Style();
    	//Word.ParagraphFormat pf = p.Format;
    	string temp = p.Range.Text;
    	if (style.NameLocal.Contains("标题") &&
    	   style.ListLevelNumber > 0) {
    	}
    }

    this will be consume:18.2933248 (/s)

    and change the code:

    Word.Paragraphs ps = this.piaDocument.Paragraphs;
    for (int i = 1; i <= ps.Count; i++) {    // diff here
        Word.Paragraph p = ps[i];            // diff here
    	Word.Style style = (Word.Style)p.get_Style();
    	//Word.ParagraphFormat pf = p.Format;
    	string temp = p.Range.Text;
    	if (style.NameLocal.Contains("标题") &&
    	   style.ListLevelNumber > 0) {
    	}
    }
    will be consume:165.0419782 (/s)

    almost 10 times performance diff, anyone can tell me why? thanks


    • Edited by sendreams Saturday, December 7, 2013 8:49 AM
    Saturday, December 7, 2013 8:48 AM
  • I'm not familiar with the way you show the performance. Which is faster?

    Cindy Meister, VSTO/Word MVP, my blog

    Saturday, December 7, 2013 11:50 AM
    Moderator
  • Hello sendreams,

    The difference between loops comes from the .Net nature (how the runtime treats COM object references and when the garbage collector is called). I would recommend releasing references in the loop:

    Word.Paragraphs ps = this.piaDocument.Paragraphs;
    for (int i = 1; i <= ps.Count; i++) 
    {    
        Word.Paragraph p = ps[i];            
        Word.Style style = (Word.Style)p.get_Style();
        Word.Range range = p.Range;
    
        string temp = range.Text;
        if (style.NameLocal.Contains("标题") &&
    	   style.ListLevelNumber > 0) 
        {
        }
     
        Marshal.ReleaseComObject(range); range = null;
        Marshal.ReleaseComObject(style); style = null;
        Marshal.ReleaseComObject(p); p = null;
    }
    
    Marshal.ReleaseComObject(ps); ps = null;
    What values do you get now?
    Saturday, December 7, 2013 12:52 PM
  • hi, Eugene_Astafiev

    your code can't made performance better,  i found the reason not only the loop but also the ps.Count consume, this method will be waste 80 Milliseconds one time.

    so the total waste time will be:1429 * 0.080 = 114.3 (s)

    Sunday, December 8, 2013 2:52 AM
  • hi, Cindy

    the foreach loop will have better performance than for (,,) in my test

    Sunday, December 8, 2013 2:53 AM
  • i use the code below and the total time will be reduce to:72.753 seconds

    int totalCount = ps.Count;   // use a temp variable will get better performance
    for (int i = 1; i <= totalCount; i++) {
    	Word.Paragraph p = ps[i];
    	Word.Style style = (Word.Style)p.get_Style();
    	Word.Range range = p.Range;
    
    	string temp = range.Text;
    	if (style.NameLocal.Contains("标题") &&
    	   style.ListLevelNumber > 0) {
    	}
    
    	COM.ReleaseComObject(range);
    	COM.ReleaseComObject(style);
    	COM.ReleaseComObject(p);
    }

    in a word, the foreach is better than for(,,) in vsto, the diff performance is 18(s) to 72(s), almost 4 times diff.

    and i found a another problem which i think will be a bug, if i open a document before than vsto running, when use vsto open the document again, the word will be show a dialog which give you 3 options, the default selected option is "use the readonly copy",than click "ok", the memory will be booming. if i don't kill the process the memory will be grow up to >2G, but the document only 4MB. you can use above test code to reproduce. 

    perhaps you can look the below picture in my skydriver first:

    https://pjkzua.dm2303.livefilestore.com/y2pRoj7c7XHpgFsEev8pRz7oChJA1vt9EzG0tpzxbWx70w1ul6d_2E8Leqn2tx2FD4_Va_l3opCWZhUVYHDaQ7EPuLs-8AU_QuSAIxJXDfdXm8/usereadonlycopy.png?psid=1
    
    https://pjkzua.dm2304.livefilestore.com/y2pbilanXKZrfvS_xM1Ox5xxwXcI-Fv7W3vKfF_yiGWNrPjKLeHsxuubEbyEbTmSntmg9xqLRs5F6JcXKSub2IjY38cL0CTf72sX3YJUMX9PXA/thememory.png?psid=1

    Sunday, December 8, 2013 3:22 AM
  • Hi sendreams

    Thank you for the additional information.

    Indeed, each call you make to the COM application will have a significant time hit. So moving the .Count property outside the loop so that you call it only the one time will help.

    The other factor in the two loops is that each time you do p(i) Word needs to calculate which paragraph. With ForEach Word should have already "built" a collection (think along the lines of IEnumerable) and works it's way through that.

    << i found a another problem >>

    Please start a new discussion for topics different than the original subject. I can tell you, however, that what you're seeing is not a bug but the result of an existing file lock. If you want to pursue the topic I need more information about when/how VSTO is loading, when/how the document is being opened (and re-opened) and any other related information. FWIW, however, I'd try removing the ReleaseCOMObject calls you built into the loop...


    Cindy Meister, VSTO/Word MVP, my blog

    Sunday, December 8, 2013 7:54 AM
    Moderator
  • Hello Cindy,

    >> FWIW, however, I'd try removing the ReleaseCOMObject calls you built into the loop...

    The ReleaseComObject call is a must for .Net developers. Plenty of articles exist in blogs describing similar scenarios. I would recommend using the for loop instead of the foreach and call the ReleaseComObject method against each object which represents a COM reference. For example, please take a look the VSTO and COM Interop article.

    Sunday, December 8, 2013 9:40 AM
  • hi Cindy

    thank you very much.

    i have little confuse about your advice, in the vsto develop should i use explicit code to release COM object? in some thread i have see somebody use this code.

    if i misunderstand your meaning i apologize for my poor english.

    Sunday, December 8, 2013 9:54 AM
  • Hi sendreams / Eugene

    Reference:http://msdn.microsoft.com/en-us/library/office/aa679807(v=office.11).aspx#officeinteroperabilitych2_part2_rco
    http://blogs.msdn.com/b/eric_carter/archive/2004/04/07/108898.aspx
    http://social.msdn.microsoft.com/Forums/office/en-US/3f9625a2-779e-42e8-beb7-41d8c85eb3ff/when-should-i-call-marshalreleasecomobject?forum=worddev

    The problem with using ReleaseCOMObject is that you could end up "orphaning" objects you still need to work with. The standard way to release objects is to set them to null (r=null;), in the reverse order they were created.

    I agree, in this particular case the objects are declared and released within the same loop so it shouldn't be a problem. And I wouldn't have mentioned it if not for the new problem: "if i open a document before than vsto running, when use vsto open the document again, the word will be show a dialog "

    If this wasn't happening before, but has started since the changes discussed here were implemented, then not using ReleaseCOMObject would be the first thing I'd change.


    Cindy Meister, VSTO/Word MVP, my blog

    Monday, December 9, 2013 7:49 AM
    Moderator
  • >> The standard way to release objects is to set them to null (r=null;), in the reverse order they were created.

    In that case you need to call GC.Collect and GC.WaitForPendingFinalizers methods twice. But if you use the Marshal.ReleaseComObject method you don't need to call the garbage collector's methods.

    Monday, December 9, 2013 1:51 PM
  • Hi Eugene

    You don't need to explicitly call garbage collection. The object will get cleaned up, eventually. But if you want to be sure the resources have been completely released then, yes, you do have to call it twice.


    Cindy Meister, VSTO/Word MVP, my blog

    Tuesday, December 10, 2013 9:41 AM
    Moderator