【发布时间】:2014-03-31 18:49:47
【问题描述】:
我正在使用 MonoGame 将 Windows Phone 7 游戏移植到 Windows Phone 8。我的游戏使用 Texture2D.FromStream 从 Internet 加载图片,一旦它尚未在 MonoGame 中实现,我正在尝试建议的解决方法:在 UI 线程中加载带有 BitmapImage 的图片。
代码如下:
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-thread调度程序。 游戏是由MonoGame模板为VS2012制作的WP8项目。 我尝试在主线程(游戏构造函数)中获取并保存到静态变量调度程序和 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() 中等待时,似乎有什么东西阻止了主线程运行。
【问题讨论】:
-
如果您在 UI 线程(即加载或启动等)上获取 Deployment.Current.Dispatcher 值并存储它,这会有所不同吗?
-
@Tertium,你为什么不在这里简单地使用
uiThread.Send,而不是使用Post和Monitor.Pulse? -
@PeterRitchie 不,这没有帮助
-
@Noseratio 我认为问题更深,发送也不起作用
-
@Tertium,您发布的代码片段不足以进一步说明这一点。
标签: c# multithreading windows-phone-8 monogame begininvoke