Потоки в XNA - PullRequest
       6

Потоки в XNA

3 голосов
/ 02 июля 2010

У меня есть игра на XNA, которая должна выполнять сетевые вызовы.В методе обновления я определяю, что нужно отправить, а затем добавляю его в список отправляемых материалов.Затем я запускаю сетевой вызов.Это сильно замедляет работу приложения.Поэтому я сначала попытался создать новый поток, подобный этому, в обновлении, чтобы он делал это в отдельном потоке:

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

Я предполагаю, что создание потоков имеет накладные расходы и т. Д., Что приводит к тому, что это становится еще медленнее.Наконец, я создал метод, содержащий while(true){DoNetworkThing();}, который будет повторять цикл и снова и снова запускать сетевой вызов (он проверяет, занят ли он уже одним и есть ли материал для отправки).Этот метод я вызвал в методе LoadContent в потоке, поэтому он будет запускаться вместе с игрой в своем собственном потоке.Но это тоже очень медленно.

Так что же я делаю не так?Каков наилучший способ сделать это?Спасибо

Ответы [ 3 ]

13 голосов
/ 02 июля 2010

У меня была именно эта проблема при первоначальной попытке использовать потоки в XNA - добавление потока замедляло все.Выяснилось, что проблема связана с привязкой потоков.

На Xbox 360 по умолчанию все потоки работают на одном и том же ядре процессора;это поведение отличается от Windows, где ядро ​​размещает потоки на другие ядра для вас.(Подробности см. В этой теме в социальной сети MSDN.)

Чтобы обойти это, вам нужно установить привязку вашего потока к другому ядру в функции потока:

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

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

В документации для Thread.SetProcessorAffinity говорится, что в XNA ядра 0 и 2 зарезервированы для платформы;Core 1 и Core 3-5 бесплатны для вашего использования.Основной поток (поток, содержащий вашу функцию main()) будет на ядре 1. Приведенный выше код произвольно устанавливает поток для запуска на ядре 3, но вы можете выбрать другое ядро ​​или добавить код для программного выбора ядра (котороевы можете захотеть сделать это, если у вас несколько потоков).

Наконец, обратите внимание, что #ifdef guard - Thread.SetProcessorAffinity доступен только на Xbox;он даже не скомпилируется в Windows!

1 голос
/ 02 июля 2010

ОК, поэтому, во-первых, создание нового потока имеет некоторые минимальные накладные расходы, но вы создаете поток только один раз (или несколько раз) ... так, если вы не создаетесотни потоков (что не должно быть), тогда вам не нужно беспокоиться о накладных расходах.

Давайте рассмотрим ваш первый пример:

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

Если вы придерживалисьВ этой модели функция DoNetworkThing будет выглядеть следующим образом:

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

Я предполагаю, что в вашей следующей попытке вы сделали что-то вроде этого:

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

Оба подхода хороши, ноединственное отличие - содержание DoNetworkingThing.Во втором подходе это будет выглядеть так:

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

Теперь вы сказали, что обе эти попытки действительно медленны, но ничто из приведенных в ваших примерах не будет указывать на то, что должно быть какое-либо заметное снижение производительности.Было бы здорово, если бы вы могли:

  1. Приведите пример, демонстрирующий замедление.
  2. Расскажите, сколько ядер у вас на машине, на которой запущена игра.

Наконец, если вы смешиваетесь с потоками, я бы СИЛЬНО предложил вам взять хорошую книгу о многопоточности и действительно ознакомиться сконцепции, стоящие за этим, пройти упражнения и написать пару простых программ.Это займет у вас пару месяцев, но если вы не знакомы с многопоточностью, это поможет вам научиться избегать множества безобразных ошибок.

Многие люди рекомендуют Joe Duffy's ConcurrentПрограммируюсь в Windows , но не стесняйтесь проверять некоторые другие многопоточные книги по C # .

0 голосов
/ 01 ноября 2012

Возможно, стоит проверить, улучшает ли использование ThreadPool производительность. Создание многих тем может быть дорогим.

http://msdn.microsoft.com/en-us/library/h4732ks0(v=vs.100).aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...