我只是在使用 WPF 和 C# 编写我的第一个程序。我的窗口只包含一个简单的画布控件:
<StackPanel Height="311" HorizontalAlignment="Left" Name="PitchPanel" VerticalAlignment="Top" Width="503" Background="Black" x:FieldModifier="public"></StackPanel>
这工作正常,从Window.Loaded
事件中我可以访问这个名为PitchPanel
.
现在我添加了一个名为的类Game
,它的初始化如下:
public Game(System.Windows.Window Window, System.Windows.Controls.Canvas Canvas)
{
this.Window = Window;
this.Canvas = Canvas;
this.GraphicsThread = new System.Threading.Thread(Draw);
this.GraphicsThread.SetApartmentState(System.Threading.ApartmentState.STA);
this.GraphicsThread.Priority = System.Threading.ThreadPriority.Highest;
this.GraphicsThread.Start();
//...
}
如您所见,有一个名为GraphicsThread
. 这应该以尽可能高的速率重绘当前游戏状态,如下所示:
private void Draw() //and calculate
{
//... (Calculation of player positions occurs here)
for (int i = 0; i < Players.Count; i++)
{
System.Windows.Shapes.Ellipse PlayerEllipse = new System.Windows.Shapes.Ellipse();
//... (Modifying the ellipse)
Window.Dispatcher.Invoke(new Action(
delegate()
{
this.Canvas.Children.Add(PlayerEllipse);
}));
}
}
但是,尽管我使用了由在创建游戏实例时传递的主窗口调用的调度程序,但发生了未处理的异常:[System.Reflection.TargetInvocationException]
,内部异常说我无法访问该对象,因为它由另一个线程拥有(主线程)。
游戏在应用程序的 Window_Loaded-event 中初始化:
GameInstance = new TeamBall.Game(this, PitchPanel);
我认为这与此答案中给出的原则相同。
那么为什么这不起作用呢?有人知道如何从另一个线程调用控件吗?