Silverlight 从不通过 WP 8.1 上的调度程序在 UI 线程上执行代码
Silverlight never executing code on UI Thread throught dispatcher on WP 8.1
我的目标是播放一些动画并让 UI 等到它完成后再执行一些其他代码。我有一个 class 这样的:
class Game
{
private string currentClickedCommand;
private string currentClickedSlot;
private GamePage gamePage;// gamePage na kojem se vrsi radnja
private string[] chosenCommands;// ovo je string array u kojem su sadrzana imena odabranih komandi
private int chapterNumber;
// Kontekst stranice koristen za update objekata UI
// Za kontrolu animacija
public static bool isAnimationComplete;
private BitmapImage currentImage;
public Game(GamePage gp, int chapterNum)
{
currentClickedCommand = null;
currentClickedSlot = null;
gamePage = gp;
chapterNumber = chapterNum;
isAnimationComplete = false;
chosenCommands = new string[5];
gamePage.characterRectangle.Visibility = System.Windows.Visibility.Collapsed;
Thread AnimationThread = new Thread(playIntroAnimation);
AnimationThread.Start();
while (!isAnimationComplete) { }
loadCommands();
loadSlots();
}
public void playIntroAnimation() {
// Pretpostavljam da na osnovu baze znam koja je animacija za ovaj chapter navedena kao uvodna
Debug.WriteLine("on other thread playing animation");
// Sakrivam gridove komandi i ostalog
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
gamePage.CommandGrid.Visibility = System.Windows.Visibility.Collapsed;
gamePage.SlotGrid.Visibility = System.Windows.Visibility.Collapsed;
MessageBox.Show("Prvi dispatch");
Debug.WriteLine("prvi dispatch");
}));
// Ucitavam pozadinsku sliku preko canvasa cijelog
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
ImageBrush bgImage = new ImageBrush();
Uri imgSource = new Uri(@"Assets/Chapter backgrounds/chapter_1_introduction.png", UriKind.Relative);
BitmapImage img = new BitmapImage(imgSource);
bgImage.ImageSource = img;
gamePage.mainCanvas.Background = bgImage;
MessageBox.Show("Drugi dispatch");
}));
// Kreiram parametre animacije
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
Uri sheetSource = new Uri(@"Assets/Sheets/test_wave_sheet.png", UriKind.Relative);
currentImage = new BitmapImage(sheetSource);
currentImage.ImageOpened += new EventHandler<RoutedEventArgs>(setAnimationParams);
Image i = new Image();
i.Source = currentImage;
MessageBox.Show("Treci dispatch");
}));
// Odredjujem lika i animiram ga -- visinu i sirinu znam iz baze(kad dobavim sheet i ostalo imam gotove parametere
// sada moram hardkodirat radi testa
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
gamePage.characterRectangle.Visibility = System.Windows.Visibility.Visible;
Canvas.SetLeft(gamePage.characterRectangle, gamePage.mainCanvas.ActualWidth / 4.0);
Canvas.SetTop(gamePage.characterRectangle, gamePage.mainCanvas.ActualHeight / 5.0);
MessageBox.Show("Cetvrti dispatch");
}));
}
private void setAnimationParams(object sender, RoutedEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(() => {
AnimationClasses.AnimationParams parameters = new AnimationClasses.AnimationParams(currentImage, 462, 438, 7, true, currentImage.PixelWidth, false, 2);
new AnimationClasses.Animation().Animate(gamePage.characterRectangle, parameters);
});
}
如您所见,我一直在尝试使用 Deployment.Current... 等方法来做到这一点,但没有成功。我一直在调试,但它根本无法执行这段代码,而且什么也没有发生。
我像这样在页面上创建一个游戏实例:
public GamePage()
{
InitializeComponent();
game = new Game(this, Convert.ToInt32(PhoneApplicationService.Current.State["chapter"]));
}
我有一个静态属性 (isAnimationComplete),它在其他地方设置为 true,当动画完成时。 (loadCommands, loadSlots) 之后的 2 个命令需要等待它完成然后执行。
谢谢!
你只是陷入了僵局。
UI 线程正在调用 Game
class 的构造函数。在内部,您正在启动一个后台线程,然后循环等待:
while (!isAnimationComplete) { }
这意味着在将 isAnimationComplete
标志设置为 true 之前,UI 线程将无法用于其他操作。这永远不会发生,因为当动画执行完成时你正在这样做......正在等待 UI 线程空闲的动画。
我的目标是播放一些动画并让 UI 等到它完成后再执行一些其他代码。我有一个 class 这样的:
class Game
{
private string currentClickedCommand;
private string currentClickedSlot;
private GamePage gamePage;// gamePage na kojem se vrsi radnja
private string[] chosenCommands;// ovo je string array u kojem su sadrzana imena odabranih komandi
private int chapterNumber;
// Kontekst stranice koristen za update objekata UI
// Za kontrolu animacija
public static bool isAnimationComplete;
private BitmapImage currentImage;
public Game(GamePage gp, int chapterNum)
{
currentClickedCommand = null;
currentClickedSlot = null;
gamePage = gp;
chapterNumber = chapterNum;
isAnimationComplete = false;
chosenCommands = new string[5];
gamePage.characterRectangle.Visibility = System.Windows.Visibility.Collapsed;
Thread AnimationThread = new Thread(playIntroAnimation);
AnimationThread.Start();
while (!isAnimationComplete) { }
loadCommands();
loadSlots();
}
public void playIntroAnimation() {
// Pretpostavljam da na osnovu baze znam koja je animacija za ovaj chapter navedena kao uvodna
Debug.WriteLine("on other thread playing animation");
// Sakrivam gridove komandi i ostalog
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
gamePage.CommandGrid.Visibility = System.Windows.Visibility.Collapsed;
gamePage.SlotGrid.Visibility = System.Windows.Visibility.Collapsed;
MessageBox.Show("Prvi dispatch");
Debug.WriteLine("prvi dispatch");
}));
// Ucitavam pozadinsku sliku preko canvasa cijelog
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
ImageBrush bgImage = new ImageBrush();
Uri imgSource = new Uri(@"Assets/Chapter backgrounds/chapter_1_introduction.png", UriKind.Relative);
BitmapImage img = new BitmapImage(imgSource);
bgImage.ImageSource = img;
gamePage.mainCanvas.Background = bgImage;
MessageBox.Show("Drugi dispatch");
}));
// Kreiram parametre animacije
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
Uri sheetSource = new Uri(@"Assets/Sheets/test_wave_sheet.png", UriKind.Relative);
currentImage = new BitmapImage(sheetSource);
currentImage.ImageOpened += new EventHandler<RoutedEventArgs>(setAnimationParams);
Image i = new Image();
i.Source = currentImage;
MessageBox.Show("Treci dispatch");
}));
// Odredjujem lika i animiram ga -- visinu i sirinu znam iz baze(kad dobavim sheet i ostalo imam gotove parametere
// sada moram hardkodirat radi testa
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
gamePage.characterRectangle.Visibility = System.Windows.Visibility.Visible;
Canvas.SetLeft(gamePage.characterRectangle, gamePage.mainCanvas.ActualWidth / 4.0);
Canvas.SetTop(gamePage.characterRectangle, gamePage.mainCanvas.ActualHeight / 5.0);
MessageBox.Show("Cetvrti dispatch");
}));
}
private void setAnimationParams(object sender, RoutedEventArgs e)
{
Deployment.Current.Dispatcher.BeginInvoke(() => {
AnimationClasses.AnimationParams parameters = new AnimationClasses.AnimationParams(currentImage, 462, 438, 7, true, currentImage.PixelWidth, false, 2);
new AnimationClasses.Animation().Animate(gamePage.characterRectangle, parameters);
});
}
如您所见,我一直在尝试使用 Deployment.Current... 等方法来做到这一点,但没有成功。我一直在调试,但它根本无法执行这段代码,而且什么也没有发生。
我像这样在页面上创建一个游戏实例:
public GamePage()
{
InitializeComponent();
game = new Game(this, Convert.ToInt32(PhoneApplicationService.Current.State["chapter"]));
}
我有一个静态属性 (isAnimationComplete),它在其他地方设置为 true,当动画完成时。 (loadCommands, loadSlots) 之后的 2 个命令需要等待它完成然后执行。 谢谢!
你只是陷入了僵局。
UI 线程正在调用 Game
class 的构造函数。在内部,您正在启动一个后台线程,然后循环等待:
while (!isAnimationComplete) { }
这意味着在将 isAnimationComplete
标志设置为 true 之前,UI 线程将无法用于其他操作。这永远不会发生,因为当动画执行完成时你正在这样做......正在等待 UI 线程空闲的动画。