我正在使用MonoGame将Windows Phone 7游戏移植到Windows Phone 8。我的游戏使用Texture2D.FromStream加载来自Internet的图片,一旦它没有在MonoGame中实现,我试图提出解决方法:在UI线程中使用BitmapImage加载图片。WP8:Dispatcher.BeginInvoke不会在UI线程上执行动作
下面是代码:
Texture2D result = null;
EventWaitHandle Wait = new AutoResetEvent(false);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
BitmapImage image = new BitmapImage();
image.SetSource(stream);
WriteableBitmap writeImage = new WriteableBitmap(image);
var index = 0;
var pixels = new byte[writeImage.PixelWidth * writeImage.PixelHeight * 4];
for (var h = 0; h < writeImage.PixelHeight; h++)
for (var w = 0; w < writeImage.PixelWidth; w++)
{
var pixel = writeImage.Pixels[index++];
var wIndex = w * 4 + h * writeImage.PixelWidth * 4;
pixels[wIndex++] = (byte)(pixel >> 16 & 0xFF);
pixels[wIndex++] = (byte)(pixel >> 8 & 0xFF);
pixels[wIndex++] = (byte)(pixel >> 0 & 0xFF);
pixels[wIndex++] = (byte)(pixel >> 24 & 0xFF);
}
result = new Texture2D(graphicsDevice, writeImage.PixelWidth, writeImage.PixelHeight);
result.SetData(pixels);
Wait.Set();
});
理论上一切正常。但不知何故,行动代码永远不会被调用。 我在非ui工作线程中调用BeginInvoke,Deployment.Current.Dispatcher不为null并提供ui线程调度程序。 游戏是由VS2012的MonoGame模板制作的WP8项目。 我试图获取并保存到主线程(游戏构造函数)中的静态变量dispatcher和SynchronizationContext,以确保它们完全属于UI线程,但这没有帮助。
我也试过这样的代码:
SynchronizationContext uiThread = Hub.SyncContext;//set in main thread (Game constructor)
var waitHandle = new object();
lock (waitHandle)
{
uiThread.Post(_ =>
{
lock (waitHandle)
{
BitmapImage image = new BitmapImage();
image.SetSource(stream);
WriteableBitmap writeImage = new WriteableBitmap(image);
var index = 0;
var pixels = new byte[writeImage.PixelWidth * writeImage.PixelHeight * 4];
for (var h = 0; h < writeImage.PixelHeight; h++)
for (var w = 0; w < writeImage.PixelWidth; w++)
{
var pixel = writeImage.Pixels[index++];
var wIndex = w * 4 + h * writeImage.PixelWidth * 4;
pixels[wIndex++] = (byte)(pixel >> 16 & 0xFF);
pixels[wIndex++] = (byte)(pixel >> 8 & 0xFF);
pixels[wIndex++] = (byte)(pixel >> 0 & 0xFF);
pixels[wIndex++] = (byte)(pixel >> 24 & 0xFF);
}
result = new Texture2D(graphicsDevice, writeImage.PixelWidth, writeImage.PixelHeight);
result.SetData(pixels);
Monitor.Pulse(waitHandle);
}
}, null);
Monitor.Wait(waitHandle);
}
但同样没有运气:在等待和断点在动作代码执行停止时从来没有发射。
更新:我刚刚添加了简单的代码,只有一个日志来示例MonoGame项目。 如果我等待AutoResetEvent,我永远不会看到任何日志。当我删除are.WaitOne()行动开始工作。我用are.WaitOne(1000)取代了它,并开始按预期工作(为什么?)。 但图像加载仍然没有运气。它看起来像是阻止主线程运行,而我在are.WaitOne()等待。 https://github.com/Taggersoft/ImageTools 这个叉子是WP8准确,如果你删除喜欢的语句所有Contract.Requires它工作得很好:
如果在UI线程中(即在加载或启动等时)获得Deployment.Current.Dispatcher值并将其存储,那么这是否有所作为? –
@Tertium,为什么不在这里简单地使用'uiThread.Send',而不是使用'Post'和'Monitor.Pulse'? – Noseratio
@PeterRitchie不,这没有帮助 – Tertium