I have an update routine that runs at the launch of an app. I keep getting intermittent null reference exceptions (about 1 in 8 runs) at certain points in my code where this seems not to be possible (My gref count and memory usage are fine and I believe that I have ruled out any threading issues). They always occur at the point of calling ToList() on an IEnumerable<T> or IList<T>, or at the point of calling foreach on a List<T>. At these points I have already determined that the List/IEnumerable is not null and that is contains a number of items. In the case of the foreach loop it fails on the foreach call and never actually gets into the loop.
The routine loops through about 10 different entities and for each one creates a List<T> which it then uses to insert or update a db. For most of these entities there are about 3 points in the code where it has been known to fail (all ToList or foreach) but will only ever fails at the first point it hits a tolist or foreach for that entity type. ie the only way I get it to fail at the second point is to remove the first tolist of foreach, and the only way to get it to fail at the third point is to remove the first and second tolist or foreach. Or to put it another way if it succeeds at the first tolist or foreach call for that type it will succeed at all other points. As it is itermittent it is hard to be concrete about anything however it does not seem to occur in the emulator, only on device. My understanding of this next bit is limited so appologies if I'm way off but it seems like it could be relevant: The common point between both tolist and foreach is that they would both be calling getenumerator<T>. From my understanding jit compilation will compile code for generic types as and when it needs it, after which it reuses it. Is it possible that I am hitting some kind of jit issue as the pattern seems to fit? Any other suggestions welcome. Mono 2.10.9 Mono for Android: 4.4.55 The bits of code that fail are: 1. Calls to this bit which is from sqlite-net (as used in xamarin mobile world sample) although I've split this call up for logging. It fail on 'return ret.ToList()'. I also have logging in the executedefferedquery and can see the the IEumerable is populated fine. public List<T> ExecuteQuery<T> () { var ret = ExecuteDeferredQuery<T>(_conn.GetMapping(typeof(T))); AroundMe.AndroidHelpers.LogDebug("sqlite-c", string.Format("exe q : {0}", (ret == null).ToString())); return ret.ToList(); //return ExecuteDeferredQuery<T>(_conn.GetMapping(typeof(T))).ToList(); } 2. This is an update/insert type routine which fails on 'foreach(T entity in entities)' . I've left in all the logging that I've put in for trying to pin this down (theres a lot). protected void InsertUpdateEntities<T>(List<T> entities, string processStageName, string processStageDisplay, bool deleteExpiredEntities) where T : class, IEntity, new() { try{ if(entities == null) throw new ArgumentNullException("entities list"); Log.Debug(_logTag, string.Format("started insert, count: {0}", entities.Count.ToString())); UpdateProgressChangedEvenArgs e = new UpdateProgressChangedEvenArgs(processStageName, processStageDisplay, 0, false); AndroidHelpers.LogDebug(_logTag," insert getting ids"); IList<string> existingIds = Repository.GetIds<T>(); AndroidHelpers.LogDebug(_logTag," insert got ids"); int itemsToUpdate = entities.Count; int itemsUpdated = 0; AndroidHelpers.LogDebug(_logTag, "Transaction Starting"); Repository.BeginDbTransaction(); AndroidHelpers.LogDebug(_logTag, "Transaction Started"); Log.Debug(_logTag, string.Format("about to start for each, count: {0}", entities.Count.ToString())); // T[] entitiesArray = new T[entities.Count]; //entities.CopyTo(entitiesArray,0); // AndroidHelpers.LogDebug(_logTag, "array copied"); foreach(T entity in entities) { try{ AndroidHelpers.LogDebug(_logTag, "Checking Contains"); if(existingIds.Contains(entity.Id)) { AndroidHelpers.LogDebug(_logTag, "Checking Contains : contains"); Repository.UpdateItem<T>(entity); } else { AndroidHelpers.LogDebug(_logTag, "Checking Contains : doesn't contain"); Repository.InsertItem<T>(entity); } } catch{ Log.Error(_logTag, string.Format("Failed to insert {0}, 1d: {1}, thread {2} , {3}", typeof(T).ToString(), entity.Id, Thread.CurrentThread.ManagedThreadId , Java.Lang.Thread.CurrentThread().Id )); } itemsUpdated ++; if(itemsUpdated % 10 == 0 || itemsUpdated == itemsToUpdate) { e.ProgressPercentage = (itemsUpdated * 100)/itemsToUpdate; // UpdateProgress(e); } } // additional code removed....... } -- View this message in context: http://mono-for-android.1047100.n5.nabble.com/Possible-JIT-issue-relating-to-generic-list-tp5712901.html Sent from the Mono for Android mailing list archive at Nabble.com. _______________________________________________ Monodroid mailing list Monodroid@lists.ximian.com UNSUBSCRIBE INFORMATION: http://lists.ximian.com/mailman/listinfo/monodroid