private aaObject ObjectAttributesReady(aaObject obj)
 {
     int i = 0;
     while (i < 5)
     {
         if (obj.DoesntExist)
             return null;
         if (obj.Attributes.Count > 0)
             return obj;
         Thread.Sleep(500); //TODO: this should be refactored out to a command line switch
         i++;
     };
     //if nothing comes through by ~2s then assume that nothing is ok
     return null;
 }
 private void RemoveObject(aaObject obj)
 {
     lock (_objects) {
     _objects.Remove(obj);
         //go through each of the object attributes, and unadvise all the handles
         foreach (var attrib in obj.Attributes)
         {
             var res = from kvp in _lmxValues where kvp.Value.Attribute == attrib select kvp;
             foreach (var kvp in res.ToList())
             {
                 //LogMessage(string.Format("Removing/Unadvising {0} from the lmxValues list.", kvp.Value.Name));
                 RemoveItem(kvp.Key);
             }
         }
     }
 }
 private aaObject GetObject(string ObjectName)
 {
     try
     {
         LogMessage("Fetching object " + ObjectName);
         //If we have already retrieved the attributes for an object, then just return the values
         aaObject obj = _objects.FirstOrDefault((arg) => arg.Name == ObjectName);
         if (obj != null)
         {
             if (obj.DoesntExist)
             {
                 return null;
             }
             else
             {
                 obj.LastAccessed = DateTime.Now;
                 return obj;
             }
         }
         //we are fetching a new object
         obj = new aaObject() { Name = ObjectName, Attributes = new List<aaAttribute>()};
         lock (_objects)
         {
             lock (_lmxValues)
             {
                 //otherwise fetch the attributes
                 //Pro tip: put the brackets on the end to get an array (someone should put this in the documentation for MXAccess...)
                 LMXValue val = new LMXValue() { Name = ObjectName + "._Attributes[]", OnceOnly = true, Parent = obj };
                 int hAttribs = _lmxServer.AddItem(_hLmx, val.Name);
                 _lmxValues.Add(hAttribs, val);
                 _lmxServer.Advise(_hLmx, hAttribs);
             }
             _objects.Add(obj);
         }
         //Give the initial values time to come through on the other threads
         return ObjectAttributesReady(obj);
     }
     catch (Exception ex)
     {
         LogMessage(ex.ToString());
         return null;
     }
 }