none
Failure to reliably iterate through all elements of a COM Collection from C# .NET 4.0 RRS feed

  • Question


  • In C#, .NET 4.0, I am making a call to a COM DLL to return a collection object.
    A foreach loop steps through each element of the collection.
    In the loop, a new .NET object is created for each element of the COM collection.
    The new object is added to a new .NET collection.
    This works fine in the development environment.

    In a deployed system, is works correctly most (about 90%) of the time. 
    However, sometimes (about 5% of the time) the foreach loop finds no items in the COM collection.
    Other times (also about 5%), it finds the first 2 or 3 or ... N items. 
    Somehow, the enumeration interface exposed by the COM object is failing.

    Here is a code snippet from the COM Object, which is called NameList. 
    NOTE that the VB6 cls file was opened in a text editor to show the class and method attributes.


    VERSION 1.0 CLASS
    BEGIN
    MultiUse = -1 'True
    Persistable = 0 'NotPersistable
    DataBindingBehavior = 0 'vbNone
    DataSourceBehavior = 0 'vbNone
    MTSTransactionMode = 0 'NotAnMTSObject
    END
    Attribute VB_Name = "NameList"
    Attribute VB_GlobalNameSpace = False
    Attribute VB_Creatable = True
    Attribute VB_PredeclaredId = False
    Attribute VB_Exposed = True
    Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
    Attribute VB_Ext_KEY = "Top_Level" ,"Yes"

    Option Explicit

    Private mCol As Collection

    ' <snip> Only code related to the collection/enumeration interface is shown here

    Public Property Get Item(vntIndexKey As Variant) As NameListItem
    Attribute Item.VB_UserMemId = 0
    Set Item = Nothing
    On Error Resume Next
    Set Item = mCol(vntIndexKey)

    With Err
    If Not (.Number = 0 Or .Number = 5) Then
    .Raise .Number, TypeName(Me) & ":Item", .Description
    End If
    End With
    End Property

    Public Function Count() As Long
    Count = mCol.Count
    End Function

    Public Function NewEnum() As IUnknown
    Attribute NewEnum.VB_UserMemId = -4
    Attribute NewEnum.VB_MemberFlags = "40"
    Set NewEnum = mCol.[_NewEnum]
    End Function

    Private Sub Class_Initialize()
    Set mCol = New Collection
    End Sub

    Private Sub Class_Terminate()
    Set mCol = Nothing
    End Sub



    And here is a snippet from the .NET code which iterates through this collection:

    public static List<NameListItemDTO> MapTo(API2.NameList source)
    {
     File.AppendAllText(@"c:\NameListMapper.txt", 
       String.Format("{2:s} NameListType {0}, Source Count {1}", source.ItemType, source.Count(), DateTime.Now));
    
     List<NameListItemDTO> items = new List<NameListItemDTO>();
     foreach (API2.NameListItem item in source)
     {
      items.Add(MapTo(item));
     }
    
     File.AppendAllText(@"c:\NameListMapper.txt", 
       String.Format(" DTO Count {0}{1}", items.Count(), Environment.NewLine));
     return i
    }
    
    // The MapTo overload called above is implemented as follows:
    
    public static NameListItemDTO MapTo(NameListItem source)
    {
      NameListItemDTO item = new NameListItemDTO()
      {
        Id = source.ID.ToString(),
        CheckSum = source.Checksum,
        ClassId = source.ClassID,
        Name = source.Name
      };
      return item;
    }
    


    The first overload of MapTo is the one in which we see the failure.  The second overload is called from the first to create each new .NET element.

    The File.AppendAllText() calls show the count if the incoming COM collection and the outgoing .NET collection.
    As stated, they usually match.  In explicably, however, the outgoing collection sometimes has 0 or some other number of members.

    No error is raised.

    As stated before, we don't see the issue at all in development mode, but it has occurred three out of three deployments.

    Please help!

    Friday, August 20, 2010 2:44 PM

All replies

  • Additional info:

    I've reproduced this in a very small example application:

    1. A COM DLL (VB6) contains an unremarkable class and collection class.  It is initialized with seven elements (Dopey, Sneezy, Doc... you can guess the rest) when the collection is instantiated.
    2. A Console app (C# .NET) repeatedly instantiates the COM DLL, counts its members in a foreach loop, and tracks how many times it comes up with fewer than 7.

    Result:

    As a compiled EXE run outside the IDE, approximately 5% of the iterations report fewer than 7 items (typically zero).  In the IDE, never are fewer than seven members found.

    Also:

    I've implemented a workaround for my acute need.  I've found that I can reliably use the Count property and the explicit, numeric index to walk through the COM collection use a simple for (;;) loop rather than foreach.  (Reminder: VB6 collections are indexed from 1 to N rather than 0 to N - 1)

    This is still an issue, however, because my company plans to release this COM component as part of an API, and we'd rather not have to document that foreach won't work in Visual Studio 2010.

    My sample APP is available for upload upon request.

     

    Tuesday, August 24, 2010 1:47 PM
  • Ok... here's a little more data.

    Changing the target .NET framework version to 3.0 (from 4.0) in Visual Studio 2010 still produces an EXE that fails to enumerate the whole collection.

    Recreating the test application in Visual Studio 2008 produces an EXE that does not exhibit this problem.  It seems limited to VS2010.

    Tuesday, August 24, 2010 2:09 PM
  • Based on the information we would need to debug the sample code and more in depth analysis.

    Your issue falls into a category that we are not able to resolve using the forums.   Please visit the below link

    to see the various paid support options that are available to better meet your needs.

    http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone

    Wednesday, September 1, 2010 7:03 PM
    Moderator
  • Thanks, Billb08

    I would prefer not to utilize a paid support option to report this bug, but may choose to do so in the future.  I have, however, posted it with complete source code on connect.microsoft.com:

    https://connect.microsoft.com/VisualStudio/feedback/details/590124/failure-to-reliably-iterate-through-all-elements-of-a-com-collection

     

    There, I've received the reply that it is being investigated.  I'll leave it there for a couple of weeks.

    Tuesday, September 7, 2010 6:42 PM