XNA Creators Club Online
Page 1 of 1 (3 items)
Sort Posts: Previous Next

Invoking Content.Load with relfection causes ArgumentException

Last post 03/11/2009 7:45 PM by Shawn Hargreaves. 2 replies.
  • 03/11/2009 7:24 PM

    Invoking Content.Load with relfection causes ArgumentException

    I have a ContentLoader class that takes care of asynchronously pre-loading the content for my game. Basically, what I do is pass a dictionary of content types and the assets for each. My loader then goes through each type, builds the corresponding Content.Load<> method, loops through each asset, and loads it using MethodInfo.Invoke.

    public class ContentTypeCollection : Dictionary<Type, List<string>> { } 
     
    public static class ContentLoader { 
        /// <summary> 
        /// Wrapper class for the Load method so parameters can be passed when starting a thread 
        /// </summary> 
        private class ContentLoaderAsync { 
            private ContentManager _contentManager; 
            private ContentTypeCollection _types; 
            private Action _callback; 
     
            public ContentLoaderAsync(ContentManager contentManager, ContentTypeCollection types, Action callback) { 
                _contentManager = contentManager; 
                _types = types; 
                _callback = callback; 
            } 
     
            public void LoadAsync() { 
                Load(_contentManager, _types); 
                _callback(); 
            } 
        } 
     
        public static int SleepLength { getset; } 
     
        private static Thread _loadThread; 
     
        public static void LoadAsync(ContentManager contentManager, ContentTypeCollection types, Action loadedCallback) { 
            _loadThread = new Thread(new ContentLoaderAsync(contentManager, types, loadedCallback).LoadAsync); 
            _loadThread.Start(); 
        } 
     
        public static void Load(ContentManager contentManager, ContentTypeCollection types) { 
            foreach (Type type in types.Keys) { 
                MethodInfo loadMethod = typeof(ContentManager).GetMethod("Load").MakeGenericMethod(type); 
                foreach (string asset in types[type]) { 
                    loadMethod.Invoke(contentManager, new object[] { asset }); 
                    Thread.Sleep(SleepLength); 
                } 
            } 
        } 

    if (!_contentLoaded) { 
        ContentLoader.LoadAsync(Content, new ContentTypeCollection { 
            { typeof(SpriteFont), new List<string> { "Fonts\\Default" } } 
        }, () => _contentLoaded = true); 

    When running this, however, I get a TargetInvocationException at loadMethod.Invoke(contentManager, new object[] { asset }); whose InnerException is an ArgumentException:

    System.ArgumentException: Value does not fall within the expected range.
       at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
       at System.Collections.Generic.Dictionary`2.Insert(String key, Object value, Boolean add)
       at System.Collections.Generic.Dictionary`2.Add(String key, Object value)
       at Microsoft.Xna.Framework.Content.ContentManager.Load[T](String assetName)
       at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
       at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean verifyAccess, StackCrawlMark& stackMark)
       at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
       at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
       at MyGame.ContentLoader.Load(ContentManager contentManager, ContentTypeCollection types)
       at MyGame.ContentLoader.ContentLoaderAsync.LoadAsync()


  • 03/11/2009 7:45 PM In reply to

    Re: Invoking Content.Load with relfection causes ArgumentException

    Answer
    Reply Quote
    Nevermind, I found it. I was executing my loader in the Update method without checking if it was already loading content, so it attempted to reload everything each time Update was called, which meant duplicate keys in the ContentManager's underlying Dictionary.
  • 03/11/2009 7:45 PM In reply to

    Re: Invoking Content.Load with relfection causes ArgumentException

    It's not immediately obvious to me what would be causing this. I would start by trying to narrow down the source of the problem. First question: is it a result of how you are using reflection, or of how you are using threading? What happens if you change this code to run on the main thread, or to run on a worker thread like it does now but do the load directly instead of via reflection?
    XNA Framework Developer - blog - homepage
Page 1 of 1 (3 items) Previous Next