-4

Possible Duplicate:
WPF and cross thread operations

I am having trouble with a window in my wpf application displaying, but not updating the view. When placing the cursor over the opened window the loading icon is shown and the window is unresponsive. I am thinking this is likely due to some threading issue I don't have enough experience in seeing.


Here is the setup:

My main program runs on startup and creates and instance of a MainWindow window which implements a custom interface (IPlayer). The main program then runs a process which interracts with IPlayer to accomplish some task, the idea being that the main program requests actions from the MainWindow, which prompts the user for some sort of input and displays the results.

I'll simplify the code for clarity. Assume this program simply runs a sort of chatter bot game.

class MainProgram
{

    [STAThread]
    static void main(string[] args)
    {
        MainWindow wdw = new MainWindw();
        Game g = new Game(wdw);

        wdw.Show();
        g.RunGame();
    }

}

class Game
{
    public IPlayer p;
    Game(IPlayer) { this.p = p; }

    public RunGame()
    {
        string r = GetResponse("How was your day?");

        ...
    }
}


public partial class Human_Player : Window, IPlayer
{
    public string GetResponse(string Question)
    {
        ShowQuestion(Question);
        string r = GetResponse();
        DisplayResponse(r);
        return r;
    }

    ...
}

I gave running RunGame() in a separate thread a shot like this:

Thread thread = new Thread(new ThreadStart(game.RunGame));
thread.Start(); 

but got an InvalidOperationException in response stating "The calling thread cannot access this object because a different thread owns it."

Any help here would be appreciated since I'm pretty new to this stuff. Thanks ahead of time!


EDIT:

Just to clarify, I'm not creating any new threads at the moment. Thus I don't think I'm doing any multi-threading. I'm attempting to run game.RunGame() on the main thread after opening the window. The runGame method consists of a large loop which calls a method on the Human_Player window that changes the UI.

As far as I know there are only two threads: - Main Thread - MainProgram and Game run here. I think the windows runs here as well but I could be wrong... please clarify - Rendering Thread - the UI is rendered here.

Community
  • 1
  • 1
marrithl2
  • 23
  • 2
  • 2
  • 6
  • 3
    Just [search for the exception](http://stackoverflow.com/search?q=The%20calling%20thread%20cannot%20access%20this%20object%20because%20a%20different%20thread%20owns%20it.)... – H.B. Jan 16 '12 at 22:08
  • some .NET threading advice: only update visual objects on their own thread. are you messing with MainWindow on a separate thread? – Jake Berger Jan 16 '12 at 22:09
  • When multi-threading you can't directly access something from the UI thread. Which object throws this exception? – Jeff LaFay Jan 16 '12 at 22:11
  • Actually the way it's written right now, I'm trying to do everything from the main thread. I may be wrong but I figured this was possible since the mainProgram starts the window by calling wdw.Show() and then continues it's execution by calling game.DoSomething(). game.DoSomething() would then call a function inside the window which changes the UI and returns some result... I must be missing something here... – marrithl2 Jan 16 '12 at 22:21

2 Answers2

1

Argh, this question is asked soooo many times... You cannot update a GUI control from a different thread than the Dispatcher thread associated to the control. You will need to run your update code using Dispatcher.BeginInvoke to update the GUI from the correct thread.

If you are not running the code from a different thread then it's possible that your method is taking too long to execute, thus causing the GUI to hang because the event thread is blocked from accepting user input.

Tudor
  • 61,523
  • 12
  • 102
  • 142
  • Could explain how game.RunGame() is on a different thread than the Human_Player window? – marrithl2 Jan 16 '12 at 22:54
  • @marrithl2: Ok, if you are not using the line Thread thread = new Thread(new ThreadStart(game.RunGame)); then it is not on a different thread. Perhaps your method is taking too long to execute, thus making the GUI hang. Try do use a stopwatch and see. – Tudor Jan 16 '12 at 22:57
  • Used the stopwatch and everything seems to be running fast. The methods take less than a millisecond on the Human_Player class. The runGame method takes a while because it's running the whole game between two players, constantly calling methods between the two. (It's actually a battleship game) – marrithl2 Jan 16 '12 at 23:09
  • So if the runGame method takes a while it might be the reason for the UI to hang. – Tudor Jan 16 '12 at 23:14
  • Within the loop that is the runGame method, the time between attacks is only 11 milliseconds. That doesn't seem like much to me, but I'm not sure what it takes to kill the render thread... Essentially, the runGame method is a loop that gets attacks from each player and checks for a winner. – marrithl2 Jan 16 '12 at 23:18
  • But when does this method return? – Tudor Jan 16 '12 at 23:20
  • after a very long pause. Then how should I be breaking that up is the problem I guess... Or rather, I guess that means I should create a new thread for runGame and call Dispatcher.Invoke -> I'll give it a try – marrithl2 Jan 16 '12 at 23:23
  • So the app hangs when I call Dispatcher.Invoke(method). unsure why – marrithl2 Jan 16 '12 at 23:38
  • Try BeginInvoke. It's asynchronous. – Tudor Jan 16 '12 at 23:39
  • it may be interesting to note that the methods are all successfully completed when running on the single thread, but the UI hangs. – marrithl2 Jan 16 '12 at 23:39
  • tried the beingInvoke. The method I called needs to have a return value for the game to proceed, but I tried a different method anyways and put a breakpoint in it. The breakpoint is never reached. I spun the runGame off into a new thread in the manner mention in my original post, created a delegae for the beingInvoke call... shouldn't have missed anything – marrithl2 Jan 16 '12 at 23:47
  • problem solved. Appreciate the help sorting through this. I know it can be frustrating on the other end, especially when someone doesn't have much experience. Thanks again! – marrithl2 Jan 17 '12 at 01:46
  • -1 to question for problem solved and not marking it as and answer. +1 to answer just for hanging in there. – paparazzo Jan 17 '12 at 01:47
0

It sounds like your game code is running in a loop and stealing all your UI's processing time. It doesn't sound like you are releasing control to your dispatcher.

Your game code shouldn't loop, it should run an iteration once and then return control to the dispatcher. You need to create a timer control that will call your game code at regular intervals instead.

Bob Vale
  • 18,094
  • 1
  • 42
  • 49