Action isn't called by Dispatcher.BeginInvoke()

812 Views Asked by At

I'm building a game for Windows Phone 8 using MonoGame. A free version of it will have ads at the top. For displaying ads I'm using AdRotator. The game has option to post results to the Facebook as an image. Recently, while testing I've find out that game completely freezes while posting image to Facebook. During debugging I was able to detect code that causes that freeze. This code is a part of MonoGame:

var waitEvent = new ManualResetEventSlim(false);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
    var bitmap = new WriteableBitmap(width, height);
    System.Buffer.BlockCopy(pixelData, 0, bitmap.Pixels, 0, pixelData.Length);
    bitmap.SaveJpeg(stream, width, height, 0, 100);
    waitEvent.Set();
});

waitEvent.Wait();

So, MonoGame thread is waiting for waitEvent to be set, but action isn't called by BeginInvoke. When there is no AdControl everything is fine, so for me it looks like AdRotator and MonoGame are conflicting somehow, but I don't really understand why this could happen.

UPD: code sample that calls code from above

RenderTarget2D renderTarget = new RenderTarget2D(ScreenManager.GraphicsDevice, width, height, false, SurfaceFormat.Color, DepthFormat.Depth24);

ScreenManager.GraphicsDevice.SetRenderTarget(renderTarget);
ScreenManager.GraphicsDevice.Clear(Color.White);

SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
spriteBatch.Begin();

// drawing some graphics

spriteBatch.End();

ScreenManager.GraphicsDevice.SetRenderTarget(null);

using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
     using (var stream = store.OpenFile(FacebookShareFileName, FileMode.Create, FileAccess.ReadWrite))
     {
         renderTarget.SaveAsJpeg(stream, width, height);
     }
}

so the game freezes on

renderTarget.SaveAsJpeg(stream, width, height);
1

There are 1 best solutions below

2
Rakesh R Nair On

Try this,

Pass the Sync Context to the method.

SynchronizationContext uiThread = SynchronizationContext.Current;

    public WritableBitmap GetImage(SynchronizationContext uiThread))
    {
        WriteableBitmap bitmap = null;
        var waitHandle = new object();
        lock (waitHandle)
        {
            uiThread.Post(_ => 
            {
                lock (waitHandle)
                {
                   bitmap = new WriteableBitmap(width, height);
                   System.Buffer.BlockCopy(pixelData, 0, bitmap.Pixels, 0, pixelData.Length);
                   bitmap.SaveJpeg(stream, width, height, 0, 100);
                   Monitor.Pulse(waitHandle);
                }

            }, null);

            Monitor.Wait(waitHandle);
        }
        return bitmap;
   }

And invoke this method in a different thread;

        SynchronizationContext uiThread = SynchronizationContext.Current;
        var result = await Task.Factory.StartNew<WriteableBitmap>(() =>
        {
            return GetImage(uiThread);
        });

I didn't added the pixelData Your pixel array to the code. You please pass that information to your code. Also I typed the code from mind, not tested in VS editor. So you may find some typos, You please ignore that. Hope this will solve your issue. Enjoy coding