Chryso

Hello,

So, no, this thread is not a tutorial on how to do it. And I am a beginner at thread programming.

I ll start by explaining why and what I would like to do.

So I am planning on creating a game that can be played by multiple persons either on the same machine, or using network. I though that having a thread listening to input events was a good idea. On thread for each input devices (keyboard / mouse / game pad ... ). I also wanted to have a thread that managed rendering. And information sharing was done through a FIFO buffer. External thread are writers, while the receiving thread was the consummer.

It would be something like the following:
A "device listener thread", lets call it a playerManagement thread (PMT), receive some inputs. It treats the input, see if it is valid, if it can be done and so on. Plain treatment. Once the treatment is done, it ADDs to the FIFO buffer of the renderer thread. And the renderer thread empties the buffer when it is not empty.

So, to do the following I need thread safe code. But problems appeared before hand.
The first thing is to see if you can listen to inputs. I tried, it did not work. The renderer was working fine, but the PMT did not catch anything from the keyboard. So, loaded this forum in the C# section and asked why. Answer was: "

As far as I know (which isn't that far, really), XNA is designed for all XNA-based activity to happen on the main thread. You can certainly use other threads for background processing (and there are wonderous performance gains to be realized from doing this), but the XNA stuff has to all happen on the main thread.

"

Next came the idea of making the PMT a class inheriting the XNA game library so that it would listen to the input correctly. That would also mean that I would have 2 games running at the same time... (bad). Anyway, I tried to launch a game in a new thread and Visual C# Express started bugging me with thread safe calls. You can not call the Run() method of a game from another thread.

With the debugger help I read the thing about how to make thread safe call to windows form controls. I tried to apply that method to the game. However a game do not have a InvokeRequired() method. So,I thought about manually testing the calling thread and the current thread. I created a delegate function to call my method to call this.Run(). However, it seems like it is not working or I am having the code wrong:

creatingThread is initialized in the constructor.

public void playerInit()
{
// TODO: Player initialisation to do
if (Thread.CurrentThread != creatingThread)
{
LaunchGame d = new LaunchGame(playing);
d.Invoke();
}
else
{
this.Run();
}
}

public void playing()
{
this.Run();
}

Then I tried using mutexes. Pretty simple since it looked like the following:

public void playerInit()
{
mut.WaitOne();
this.Run();
mut.ReleaseMutex();
}

Except none of those way works.

So, how should I do thread safe calls How can I launch a game from another thread And can I have 2 game running, one to gather the input, one to render the graphics, and make them talk to each other using shared objects (themselves)

Also another question would be, since I am a beginner in thread programming:
Do I need to make method thread safe when I am only reading information

Regards,

Chryso




Re: XNA Framework How to Launch a XNA game in a new thread ?

Shawn Hargreaves - MSFT

The Win32 API is not multithreaded, so this means any code that uses Win32 has to run on your main thread. That includes reading input (which uses some Windows messages) and also the Game class because that uses Win32 to create the main game window. There is fundamentally no way to multithread this stuff: that's just the nature of Windows.

Multithreading can be used to good effect if you have multiple processors by moving processing work (physics, AI, etc) off onto a background thread, but trying to multithread the entire Game class is just going to cause trouble.

I don't understand exactly why you need to multithread your input reading This seems like a very complicated design. Why not just poll each device once at the start of your game Update method





Re: XNA Framework How to Launch a XNA game in a new thread ?

Chryso

Thank you for the insight.

Well, I mainly wanted to put it into another thread because I got lots of treatment to do on an input. Also, I was going to add an AI in another thread.

So having something that would look like the following would have been nice:
Input thread \
> Agregator + Data updater thread ===> Video renderer thread
AI thread /

I though that having a thread per blocks would make for an efficient way to manage different aspects of the game. So I guess I ll still be able to separate the AI thread.

Would, getting the inputs from the main thread and then transmit them to another thread be efficient for treatment if they can be a bit heavy

Can you use a thread for video rendering other than the main thread

Regards,
Chryso


EDIT: Anyone know a good tutorial for C# about thread safe programming




Re: XNA Framework How to Launch a XNA game in a new thread ?

The ZMan

Free ebook on multithreading in c# (yes its a legal free ebook not one of those spam's that people often post in here and I delete)




Re: XNA Framework How to Launch a XNA game in a new thread ?

Chryso

Thank you for the eBook,

Last question I guess. How can I launch a game from another thread.

If i try the following:

world.world aWorld = new world.world();
Game1 game = new Game1(aWorld);

Thread threadWorld = new Thread(new ThreadStart(aWorld.worldInit));

Thread threadGraphic = new Thread(new ThreadStart(game.Run));

threadWorld.Start();
threadGraphic.Start();
game.myLaunchGame(player,aWorld);


I have a thread-safe exception. Seems like Run() is not thread safe.
And trying the code I showed before using myLaunchGame() did not work either.

Any idea on how I could possibly do that

Regards,

Chryso




Re: XNA Framework How to Launch a XNA game in a new thread ?

Shawn Hargreaves - MSFT

You can't. The Game object creates your window, and that has to happen on the main application thread.

Leave Game on your main thread, and put your other tasks on worker threads, rather than vice versa.





Re: XNA Framework How to Launch a XNA game in a new thread ?

Chryso

Okay, thanks,

Last question, well, I think for today at least.

Can I make every calculation needed for video rendering in a separate thread and then use the main thread to output it to the screen

Would it be intelligent to do the following:

Main thread:
  • Loops through the data and makes some processing on those. It uses a FIFO buffer
  • Draws the game window
  • Check keyboard state

Other threads:
  • A thread that reads the keyboard / mouse / game pad information and makes some needed processing of the data. It update the main thread FIFO buffer
  • A thread for the IA (doable and logic) that updates the main thread FIFO buffer
  • A thread for all the video processing before drawing
With real caution regarding data sharing. And thread safety naturally.

Regards,

Chryso


Edit:
What would be the Advantages / disadvantages of such a system





Re: XNA Framework How to Launch a XNA game in a new thread ?

Shawn Hargreaves - MSFT

You can issue DirectX rendering calls from any thread you like, but not from more than one thread at the same time. So yes, it's feasible to multithread this as long as you take care of synchonising so only one thread renders at a time.

Be aware though that multithreading a game is really, really hard! This isn't something to dive into unless you're ready to spend a lot of time struggling with debugging race conditions. I wouldn't recommend doing it unless you're absolutely sure you need to.





Re: XNA Framework How to Launch a XNA game in a new thread ?

Rob Hanz

Advantages:
  • You can write code in a blocking rather than unblocking style. This can potentially lead to more straightforward code on tasks that may take a while, but should be run in the background. Database queries are potentially a good example of this.
  • You can use more cores to increase performance, if needed
Disadvantages:
  • Your code will become more complex overall, as you will have to worry about deadlocks, mutexes, critical sections, thread pool management, and all of the other fun aspects of multithreading.
  • Your code will become less stable.
  • Your code will become harder to debug.
  • The things that you're talking about putting in threads are generally not resource intensive, so performance increases will be minimal at best.
  • The things that you're talking about putting in threads aren't particularly good candidates for threads either, as none of them are fire-and-forget tasks that you only want to hear from when they're done, but may take a while to get done.
  • At this point, you don't know what your performance bottlenecks are, so speculatively improving performance by putting various tasks on different cores is probably more trouble than it is worth.
If you want to write a threaded app just for the experience, that's fine. But realistically, threading is one of those things that you should do because you *know* you have a need for it, not simply because you think it'd be cool or you *might* need it. I'd argue against coding things you *might* need as a general principle, anyway.