我正在使用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