2012-10-29 88 views
1

我只是寫我的第一個程序使用WPF和C#。我的窗戶只是包含了一個簡單的畫布控制:線程安全調用WPF控件

<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事件:

GameInstance = new TeamBall.Game(this, PitchPanel); 

我覺得這是在this answer給出了相同的原則。

那麼,爲什麼這不起作用?有人知道如何從另一個線程調用控件嗎?

+0

閱讀[線程模型參考](http://msdn.microsoft.com/en-us/library/ms741870.aspx)?另見[這個問題](http://stackoverflow.com/questions/11923865/how-to-deal-with-cross-thread-access-exceptions)。 –

回答

1

您不能在其他線程上創建WPF對象 - 它也必須在分派器線程上創建。

此:

System.Windows.Shapes.Ellipse PlayerEllipse = new System.Windows.Shapes.Ellipse(); 

必須進入委託。

+0

就是這樣。現在它似乎在工作。非常感謝。 –