简体   繁体   中英

Thread-safe calls to WPF controls

I am just writing my first program using WPF and C#. My windows just contains a simple canvas control:

<StackPanel Height="311" HorizontalAlignment="Left" Name="PitchPanel" VerticalAlignment="Top" Width="503" Background="Black" x:FieldModifier="public"></StackPanel>

This works fine and from the Window.Loaded event I can access this Canvas called PitchPanel .

Now I have added a class called Game which is initialized like this:

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();
    //...
}

As you can see, there is a thread called GraphicsThread . This should redraw the current game state at the highest possible rate like this:

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);
       }));
    }
}

But although I have used a dispatcher which is invoked by the main window which is passed at the creation of the game instance, an unhandled exception occurs: [System.Reflection.TargetInvocationException] , the inner exceptions says that I cannot access the object as it is owned by another thread (the main thread).

The Game is initialized in the Window_Loaded-event of the application:

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

I think this is the same principle as given in this answer .

So why does this not work? Does anybody know how to make calls to a control from another thread?

You cannot create a WPF object on a different thread - it must also be created on the Dispatcher thread.

This:

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

must go into the delegate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM