Texture2D.FromStream works once and then throws NullReferenceException (the last line)
public class Game1 : Game
{
...
protected override void LoadContent()
{
base.LoadContent();
var uri = new Uri(@"Content/Textures/menu-btn.png", UriKind.Relative);
var stream1 = Application.GetResourceStream(uri).Stream;
var txt1 = Texture2D.FromStream(Graphics.GraphicsDevice, stream1);
var stream2 = Application.GetResourceStream(uri).Stream;
var txt2 = Texture2D.FromStream(Graphics.GraphicsDevice, stream2);
}
{System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Xna.Framework.Graphics.Texture2D.PlatformFromStream(GraphicsDevice graphicsDevice, Stream stream)
at Microsoft.Xna.Framework.Graphics.Texture2D.FromStream(GraphicsDevice graphicsDevice, Stream stream)
at RescueTeam.Game1.LoadContent()
at Microsoft.Xna.Framework.Game.Initialize()
at RescueTeam.Game1.Initialize()
at Microsoft.Xna.Framework.Game.DoInitialize()
at Microsoft.Xna.Framework.Game.Run(GameRunBehavior runBehavior)
at MonoGame.Framework.WindowsPhone.SurfaceUpdateHandler.Draw(Device device, DeviceContext context, RenderTargetView renderTargetView)
at MonoGame.Framework.WindowsPhone.DrawingSurfaceUpdateHandler.DrawingSurfaceContentProvider.GetTexture(Size2F surfaceSize, DrawingSurfaceSynchronizedTexture& synchronizedTexture, RectangleF& textureSubRectangle)
at SharpDX.Direct3D11.DrawingSurfaceContentProviderShadow.DrawingSurfaceContentProviderVtbl.GetTexture(IntPtr thisPtr, IntPtr surfaceSize, IntPtr synchronizedTexture, IntPtr textureSubRectangle)}
WP8 as a platform has a limtation. You have to load textures using FromStream asynchronously, on a thread other than the one that calls LoadContent, Initialize, Update or Draw (so you can’t call it from these functions). You get a NullReferenceException because the game ended up in a deadlock situation, which was resolved after a few seconds, but then the game failed to load the texture.
Unfortunately, the prolem is not solved yet (
Async/await construction does not guarantee that resources are loaded in different thread and NullReferenceException sometimes is thrown.
I don’t know why, but Thread.Start also does not help:
public class Game1 : Game
...
protected override void Initialize()
{
base.Initialize();
var xxx = new System.Threading.Thread(LoadContentAsync);
xxx.Start();
xxx.Join();
...
}
public void LoadContentAsync()
{
base.LoadContent();
var backTexture = LoadTexture2D("Textures/bg1.jpg");
var middleTexture = LoadTexture2D("Textures/bg1par.png");
}
private Texture2D LoadTexture2D(string fileName)
{
var uri = new Uri(String.Format(@"Content/{0}", fileName), UriKind.Relative);
using (var stream1 = System.Windows.Application.GetResourceStream(uri).Stream)
{
return Texture2D.FromStream(sm.game1.Graphics.GraphicsDevice, stream1);
}
}
falls constantly.
I also tried to load textures in BackGroundWorker. Then in half of cases I get AccessViolationException:
{System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.}
and
System.AccessViolationException was unhandled
Message: An unhandled exception of type ‘System.AccessViolationException’ occurred in SharpDX.Direct3D11.DLL
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
What am I doing wrong?
Is there anybody who loaded .png and .jpg textures on windows phone successfully?
We load pictures from the media library using BackgroundWorker. My guess is that you are loading individual pictures asynchronously (one background worker for each picture), instead of loading all the pictures asynchronously (one background worker for the whole LoadContent). Multithreaded content loading might cause such access violation exception.
Let me clarify, are you using only one BackgroundWorker for loading resources for one game scene?
I mean, I have 2 layers (background and foreground) on screen at the same time, and they each have own LoadContent. So I guess, I have 2 BackgroundWorkers at the same time. Is it important? Shoul I write some singletone ContentManager?
EDIT:
Сonvinced myself, that 1 BackgroundWorker executes at one time. Than copied code from method
to my application, fixed dependencies.
Found that exception happens because I didn’t get here:
Threading.BlockOnUIThread(() =>
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(stream);
bitmap = new WriteableBitmap(bitmapImage);
});
and bitmap is null.
EDIT2:
we need to go deeper…
target.BeginInvoke in BlockOnContainerThread() method does not work. I load the first texture and get exception on the second one.