Index: Source/UI/SkinEngine/ContentManagement/AssetCore/TextureAssetCore.cs
===================================================================
--- Source/UI/SkinEngine/ContentManagement/AssetCore/TextureAssetCore.cs	(revision 3595)
+++ Source/UI/SkinEngine/ContentManagement/AssetCore/TextureAssetCore.cs	(working copy)
@@ -69,6 +69,7 @@
     protected float _maxU;
     protected int _allocationSize = 0;
     protected State _state = State.None;
+    protected object _syncObj = new object();
 
     protected WebClient _webClient;
     protected FileStream _fileStream;
@@ -95,7 +96,10 @@
     {
       _textureName = textureName;
       if (string.IsNullOrEmpty(_textureName))
-        _state = State.Failed;
+      {
+        lock (_syncObj)
+          _state = State.Failed;
+      }
       _decodeWidth = decodeWidth;
       _decodeHeight = decodeHeight;
     }
@@ -146,7 +150,7 @@
 
     public bool LoadFailed
     {
-      get { return _state == State.Failed; }
+      get { return CheckState(State.Failed); }
     }
 
     #endregion
@@ -174,7 +178,11 @@
     /// </summary>
     public void ClearFailedState()
     {
-      _state = State.None;
+      lock (_syncObj)
+      {
+        if (_state == State.Failed)
+          _state = State.None;
+      }
     }
 
     #endregion
@@ -187,75 +195,75 @@
     protected void Allocate(bool async)
     {
       KeepAlive();
-      if (IsAllocated || _state == State.Failed || _state == State.LoadingAsync)
+      if (IsAllocated)
         return;
 
-      // Has an Asyncronous load or web download completed?
-      if (CheckAsyncCompletion())
-        return;
+      lock (_syncObj)
+      {
+        // If data has been cached asyncronously then complete allocation now
+        if (_state == State.Loaded)
+          CompleteAsyncronousOperation();
+        else if (_state != State.None && _state != State.LoadingThumb)
+          return;
 
-      // Is the path a local skin file?
-      string sourceFilePath = SkinContext.SkinResources.GetResourceFilePath(
-        SkinResources.IMAGES_DIRECTORY + "\\" + _textureName);
-      
-      if (sourceFilePath == null || !File.Exists(sourceFilePath))
-      {
-        // Is it an absolute Uri?
-        Uri uri;
-        if (!Uri.TryCreate(_textureName, UriKind.Absolute, out uri))
+        // Is the path a local skin file?
+        string sourceFilePath = SkinContext.SkinResources.GetResourceFilePath(
+          SkinResources.IMAGES_DIRECTORY + "\\" + _textureName);
+
+        if (sourceFilePath == null || !File.Exists(sourceFilePath))
         {
-          ServiceRegistration.Get<ILogger>().Error("Cannot open texture :{0}", _textureName);
-          _state = State.Failed;
-          return;
+          // Is it an absolute Uri?
+          Uri uri;
+          if (!Uri.TryCreate(_textureName, UriKind.Absolute, out uri))
+          {
+            ServiceRegistration.Get<ILogger>().Error("Cannot open texture :{0}", _textureName);
+            _state = State.Failed;
+            return;
+          }
+          else if (uri.IsFile)
+            sourceFilePath = uri.LocalPath;
+          else
+          {
+            AllocateFromWeb_NeedsLock(uri);
+            return;
+          }
         }
-        else if (uri.IsFile)
-          sourceFilePath = uri.LocalPath;
-        else
+
+        if (UseThumbnail)
         {
-          AllocateFromWeb(uri);      
-          return;
+          IAsyncThumbnailGenerator generator = ServiceRegistration.Get<IAsyncThumbnailGenerator>();
+          ImageType imageType;
+          if (generator.GetThumbnail(sourceFilePath, out _imageBuffer, out imageType))
+            AllocateFromInternalBuffer_NeedsLock();
+          else
+            _state = State.LoadingThumb;
         }
-      }
-      
-      if (UseThumbnail)
-      {
-        IAsyncThumbnailGenerator generator = ServiceRegistration.Get<IAsyncThumbnailGenerator>();
-        ImageType imageType;
-        if (generator.GetThumbnail(sourceFilePath, out _imageBuffer, out imageType))
-          AllocateFromInternalBuffer();
+        else if (async)
+          AllocateFromFileAsync_NeedsLock(sourceFilePath);
         else
-          _state = State.LoadingThumb;
+          AllocateFromFile_NeedsLock(sourceFilePath);
       }
-      else if (async)
-        AllocateFromFileAsync(sourceFilePath);
-      else
-        AllocateFromFile(sourceFilePath);
     }
 
-    protected bool CheckAsyncCompletion()
+    protected void CompleteAsyncronousOperation()
     {
-      if (_state == State.Loaded)
-      {
-        if (_imageDataStream != null)
-          AllocateFromInternalDataStream();
-        else if (_imageBuffer != null)
-          AllocateFromInternalBuffer();
-        else
-          throw new InvalidDataException("Unexpected data state encountered");
-        return true;
-      }
-      return false;
+      if (_imageDataStream != null)
+        AllocateFromInternalDataStream_NeedsLock();
+      else if (_imageBuffer != null)
+        AllocateFromInternalBuffer_NeedsLock();
+      else
+        _state = State.Failed;
     }
 
-    protected void AllocateFromFile(string path)
+    protected void AllocateFromFile_NeedsLock(string path)
     {
       ImageInformation info;
       _texture = Texture.FromFile(GraphicsDevice.Device, path, _decodeWidth, _decodeHeight, 1, Usage.None, Format.A8R8G8B8,
           Pool.Default, Filter.None, Filter.None, 0, out info);
-      FinalizeAllocation(info.Width, info.Height);
+      FinalizeAllocation_NeedsLock(info.Width, info.Height);
     }
 
-    protected void AllocateFromFileAsync(string path)
+    protected void AllocateFromFileAsync_NeedsLock(string path)
     {
       try {
         // Create a FileStream for Asyncronous access.
@@ -275,28 +283,28 @@
       {
         ServiceRegistration.Get<ILogger>().Error("Contentmanager: Image '{0}' could not be opened: {1}", e);
         _state = State.Failed;
-        FreeTemporaryResources();
+        FreeTemporaryResources_NeedsLock();
       }
     }
 
-    protected void AllocateFromInternalDataStream()
+    protected void AllocateFromInternalDataStream_NeedsLock()
     {
       ImageInformation info;
       _imageDataStream.Seek(0, SeekOrigin.Begin);
       _texture = Texture.FromStream(GraphicsDevice.Device, _imageDataStream, 0, _decodeWidth, _decodeHeight, 1, 
           Usage.None, Format.A8R8G8B8, Pool.Default, Filter.None, Filter.None, 0, out info);
-      FinalizeAllocation(info.Width, info.Height);
+      FinalizeAllocation_NeedsLock(info.Width, info.Height);
     }
 
-    protected void AllocateFromInternalBuffer()
+    protected void AllocateFromInternalBuffer_NeedsLock()
     {
       ImageInformation info;
       _texture = Texture.FromMemory(GraphicsDevice.Device, _imageBuffer, _decodeWidth, _decodeHeight, 1, Usage.None, Format.A8R8G8B8, 
         Pool.Default, Filter.None, Filter.None, 0, out info);
-      FinalizeAllocation(info.Width, info.Height);
+      FinalizeAllocation_NeedsLock(info.Width, info.Height);
     }
 
-    protected void AllocateFromWeb(Uri uri)
+    protected void AllocateFromWeb_NeedsLock(Uri uri)
     {
       if (_webClient != null)
         _webClient.Dispose();
@@ -311,7 +319,7 @@
       _state = State.LoadingAsync;
     }
 
-    void FinalizeAllocation(int fileWidth, int fileHeight)
+    void FinalizeAllocation_NeedsLock(int fileWidth, int fileHeight)
     {
       if (_texture != null)
       {
@@ -327,10 +335,10 @@
       else
         _state = State.Failed;
 
-      FreeTemporaryResources();
+      FreeTemporaryResources_NeedsLock();
     }
 
-    void FreeTemporaryResources()
+    void FreeTemporaryResources_NeedsLock()
     {
       if (_fileStream != null)
         _fileStream.Dispose();
@@ -347,42 +355,61 @@
       _imageBuffer = null;
     }
 
+    protected bool CheckState(State testState)
+    {
+      lock (_syncObj)
+        return _state == testState;
+    }
+
     #endregion
 
     #region Asyncronous callbacks
 
     protected void WebDownloadComplete(object sender, DownloadDataCompletedEventArgs e)
     {
-      FreeTemporaryResources();
-      if (e.Error != null)
+      lock (_syncObj)
       {
-        ServiceRegistration.Get<ILogger>().Error("Contentmanager: Failed to download {0} - {1}", _textureName, e.Error.Message);
-        _state = State.Failed;
-        return;
+        // Check that we haven't been freed while loading the file
+        if (_webClient == null)
+          return;
+
+        FreeTemporaryResources_NeedsLock();
+        if (e.Error != null)
+        {
+          ServiceRegistration.Get<ILogger>().Error("Contentmanager: Failed to download {0} - {1}", _textureName, e.Error.Message);
+          _state = State.Failed;
+          return;
+        }
+        // Store image data for allocation later
+        _imageBuffer = e.Result;
+        _state = State.Loaded;
       }
-      // Store image data for allocation later
-      _imageBuffer = e.Result;
-      _state = State.Loaded;
     }
 
     protected void AllocateAsyncCallback(IAsyncResult result)
     {
-      int read = _fileStream.EndRead(result);
+      lock (_syncObj)
+      {
+        // Check that we haven't been freed while loading the file
+        if (_imageDataStream == null || _fileStream == null)
+          return;
 
-      if (read == 0)
-      {
-        // File read complete
-        _state = State.Loaded;
-        _fileStream.Dispose();
-        _fileStream = null;
-        _imageBuffer = null;
+        int read = _fileStream.EndRead(result);
+        if (read == 0)
+        {
+          // File read complete
+          _state = State.Loaded;
+          _fileStream.Dispose();
+          _fileStream = null;
+          _imageBuffer = null;
+        }
+        else        
+        {
+          // Read next chunk
+          _imageDataStream.Write(_imageBuffer, 0, read);
+          _fileStream.BeginRead(_imageBuffer, 0, _imageBuffer.Length, AllocateAsyncCallback, null);
+        }
       }
-      else
-      {
-        // Read next chunk
-        _imageDataStream.Write(_imageBuffer, 0, read);
-        _fileStream.BeginRead(_imageBuffer, 0, _imageBuffer.Length, AllocateAsyncCallback, null);
-      }
     }
 
     #endregion
@@ -401,16 +428,17 @@
 
     public void Free()
     {
-      if (_texture != null)
+      lock (_syncObj)
       {
-        lock (_texture)
+        if (_texture != null)
         {
           AllocationChanged(-AllocationSize);
           _texture.Dispose();
           _texture = null;
         }
+        FreeTemporaryResources_NeedsLock();
+        _state = State.None;
       }
-      FreeTemporaryResources();
     }
 
     #endregion
@@ -464,5 +492,10 @@
         base.FireAllocationChanged(_allocationSize);
       }
     }
+
+    public override void AllocateAsync()
+    {
+      Allocate();
+    }
   }
 }
\ No newline at end of file
