views:

86

answers:

2
+1  Q: 

Threading in XNA

I have a game in XNA which needs to do network calls. In the update method I determine what needs to be sent and then add it to a list of stuff to send. Then I run the network call. This slows down the application alot obviously. So I first tried creating a new thread like this in the update to make it do it on a seperate thread:

Thread thread; 
thread = new Thread(
new ThreadStart(DoNetworkThing));
thread.Start();

I presume creating threads has overhead etc which results in this being even slower. Finally, I made a method that has while(true){DoNetworkThing();} in it which will keep looping round and run the network call over and over again(it does check if its already busy with one, and whether there is stuff to send). That method I called in the LoadContent method in a thread, so it will run alongside the game in its own thread. But that is really slow too.

So what am I doing wrong? What is the best way of doing this? Thanks

+1  A: 

OK, so first of all- creating a new thread does have some minimal overhead, but you're only creating the thread once (or a few times)... so unless you're creating hundreds of threads (which you shouldn't be), then you will not need to worry about the overhead.

Let's look at your first example:

Thread thread; 
thread = new Thread(new ThreadStart(DoNetworkThing));

// you should set the thread to background, unless you 
// want it to live on even after your application closes
thread.IsBackground = true;
thread.Start();

If you were sticking with that model, the DoNetworkThing function would look like this:

void DoNetworkThing()
{
    while(someConditionIsTrue)
    {
        // do the networking stuff here
    }
}

I presume that in your next attempt you did something like this:

Thread thread = new Thread(()=>
   {
       while(true)
       {
           DoNetworkThing();
       }
   });
thread.IsBackground = true;
thread.Start();

Both approaches are fine, but the only difference is the content of DoNetworkingThing. In the second approach it will look like this:

void DoNetworkThing()
{
    // do the networking thing, but note
    // that this time your infinite while
    // loop is outside the function
}

Now you said that both of these attempts are really slow, but nothing given in your examples would indicate that there should be any noticeable performance impact. It would be great if you can:

  1. Give us an example that would demonstrate the slow down.
  2. Tell us how many cores you have on the machine that the game is running on.

Finally, if you're mingling with threads then I would STRONGLY suggest that you pickup a good book on multithreading and really familiarize yourself with the concepts behind it, go through the exercises and write a couple of simple programs. It will take you a couple of months, but if you're not familiar with threading then it will help you learn how to avoid a lot of ugly mistakes.

A lot of people recommend Joe Duffy's Concurrent Programming on Windows, but feel free to check some other C# multithreading books too.

Lirik
+5  A: 

I had this exact problem when initially attempting to use threads on XNA -- adding a thread slowed everything down. It turned out that thread affinity was the issue.

On Xbox 360, by default, all threads run on the same processor core; this behaviour differs from Windows, where the kernel places threads onto other cores for you. (See answers on this thread at MSDN social for detail.)

To get around it, you need to set the affinity for your thread to another core in your thread function:

void DoNetworkThing()
{
#ifdef XBOX
    Thread.SetProcessorAffinity(3); // see note below
#endif
    /* your code goes here */
}

Thread thread = new Thread(
 new ThreadStart(DoNetworkThing));
thread.Start();

The documentation for Thread.SetProcessorAffinity states that on XNA, cores 0 and 2 are reserved for the framework; core 1 and cores 3-5 are free for your use. The main thread (the thread containing your main() function) will be on core 1. The code above arbitrarily sets the thread to run on core 3, but you can choose a different core, or add code to programmatically choose a core (which you may want to do if you have more than a few threads).

Finally, note the #ifdef guard - Thread.SetProcessorAffinity is only available on Xbox; it won't even compile on Windows!

Blair Holloway
Although I am still stuck, this is the closest answer. Thanks :)
Matt