Я разрабатываю игру с использованием TCP. Клиенты отправляют и слушают сервер, используя TCP. Когда сервер получает запрос, он обращается к базе данных (SQL Server Express / Entity Framework) и отправляет ответ клиенту.

Я пытаюсь создать MMORPG, поэтому мне нужно часто знать местоположения всех игроков, поэтому я использовал System.Timer , чтобы запросить у сервера местоположение игроков вокруг меня.

Проблема:

Если я настрою таймер на срабатывание каждые 500 мс метода, который запрашивает у сервера текущее местоположение игроков, тогда я могу открыть 2 экземпляра клиентского приложения, но оно будет тормозить. Если я настрою запускать каждые 50 мсек, то при открытии второго экземпляра SQL Server часто выдает это исключение:

«Соединение не было закрыто. Текущее состояние соединения открыто».

Я имею в виду, какого черта? Я знаю, что за короткий период времени запрашиваю МНОГОЕГО в базе данных, но как с этим справляются настоящие игры?

Вот один код, который выдает ошибку, когда кажется, что SQL Server перегружен (вторая строка метода):

private List<CharacterDTO> ListAround()
    {
        List<Character> characters = new List<Character>();
        characters = ObjectSet.Character.AsNoTracking().Where(x => x.IsOnline).ToList();

        return GetDto(characters);
    }
0
alansiqueira27 10 Мар 2014 в 01:09
Возможно, мой вопрос можно было бы перенести на gamedev.stackexchange.com. Я только что это заметил.
 – 
alansiqueira27
10 Мар 2014 в 01:19
Я только что узнал, что не должен хранить в постоянной памяти (базе данных) местоположение игроков в реальном времени. Вместо этого я должен хранить в оперативной памяти и реже обновлять базу данных. Я собираюсь попробовать это!
 – 
alansiqueira27
10 Мар 2014 в 01:45
Не могли бы вы хотя бы опубликовать код, который вы используете для установления TCP-соединения?
 – 
Slugart
10 Мар 2014 в 01:59
@Slugart, проблема с SQL Server. Не ПТС. Ошибка возникает, когда я использую запрос к базе данных.
 – 
alansiqueira27
10 Мар 2014 в 02:18
1
Возможно, ваша проблема связана с потоками: stackoverflow.com/questions/12521695/…
 – 
Slugart
10 Мар 2014 в 02:30

2 ответа

Лучший ответ

Решил проблему изменением стратегии. Теперь я не обновляю позиции игроков в базе данных в реальном времени. Вместо этого я создал список (оперативная память) на сервере, поэтому я управляю только этим списком. Со временем я обновлю информацию в базе данных.

0
alansiqueira27 10 Мар 2014 в 03:10

Ваша настоящая проблема в том, что ObjectSet не является потокобезопасным. Вы должны создать новый контекст базы данных внутри ListAround и удалить его, когда закончите с ним, а не повторно использовать один и тот же контекст снова и снова.

private List<CharacterDTO> ListAround()
{
    List<Character> characters = new List<Character>();

    using(var ObjectSet = new TheNameOfYourDataContextType())
    {
        characters = ObjectSet.Character.AsNoTracking().Where(x => x.IsOnline).ToList();

        return GetDto(characters);
    }
}
1
Scott Chamberlain 10 Мар 2014 в 03:17