2009-09-10 2 views
0

Я читал и смотрел довольно много примеров для Threadpooling, но я просто не могу понять, как они мне нужны. То, что мне удалось получить, - это не то, что мне нужно. Он просто запускает функцию в своем потоке.C# Threadpooling HttpWebRequests

public static void Main() 
    { 
     while (true) 
     { 
      try 
      { 
       ThreadPool.QueueUserWorkItem(new WaitCallback(Process)); 
       Console.WriteLine("ID has been queued for fetching"); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("Error: " + ex.Message); 
      } 
      Console.ReadLine(); 
     } 
    } 

public static void Process(object state) 
{ 

    var s = StatsFecther("byId", "0"); //returns all player stats 
    Console.WriteLine("Account: " + s.nickname); 
    Console.WriteLine("ID: " + s.account_id); 
    Console.ReadLine(); 
} 

То, что я пытаюсь сделать, это около 50 нитей происходит (возможно, больше), что выборки данных в последовательную форму PHP, содержащие статистику игрока. Начиная с пользователя 0, вплоть до идентификатора пользователя, я указываю (300 000). Мой вопрос заключается не в том, как получить статистику, я знаю, как получить статистику и прочитать их, но как я пишу Threadpool, который будет продолжать получать статистику, пока не получит 300 000-й идентификатор пользователя, не наступая на носки других потоков и сохраняет статистику, когда она извлекает их в базу данных.

+0

50 потоков одновременно хранящихся данных? По всей вероятности, ваша синхронизация будет вашей самой большой проблемой. – spender

ответ

3
static int _globalId = 0; 
public static void Process(object state) 
{  
    // each queued Process call gets its own player ID to fetch 
    processId = InterlockedIncrement(ref _globalId); 
    var s = StatsFecther("byId", processId); //returns all player stats 

    Console.WriteLine("Account: " + s.nickname);  
    Console.WriteLine("ID: " + s.account_id);  
    Console.ReadLine(); 
} 

Это простейшая вещь. Но далеко не оптимальный. Вы используете синхронные вызовы, полагаетесь на ThreadPool для дросселирования скорости звонка, у вас нет политики повторных попыток для неудачных вызовов, и ваше приложение будет плохо работать в условиях ошибок (когда веб-вызовы не работают).

Прежде всего вам следует рассмотреть возможность использования асинхронных методов WebRequest: BeginGetRequestStream (если вы используете POST и имеете тело запроса) и/или BeginGetResponse. Эти методы масштабируются намного лучше, и вы получите более высокий коэффициент пропускания для меньшего количества процессоров (если задняя часть может быть в курсе, конечно).

Во-вторых, вы должны подумать о самоутверждении. В аналогичном проекте я использовал подсчет ожидающего запроса. При успешном завершении каждого вызова будет отправлено еще 2 звонка, ограниченное счетом триллинга. При сбое звонок ничего не подал. Если запросы не ожидаются, повторная попытка по таймеру отправляет новый вызов каждую минуту. Таким образом, вы пытаетесь только один раз в минуту, когда служба отключается, сохраняя ваши собственные ресурсы от вращения без тяги, и вы увеличиваете пропускную способность до колпака триптирования при обслуживании.

Вы также должны знать, что инфраструктура .Net ограничит количество согласованных подключений, которые она делает для любого ресурса. Вы должны найти свой пункт назначения ServicePoint и изменить ConnectionLimit со своего значения по умолчанию (2) на максимальное значение, которое вы хотите включить.

О части обновления базы данных, есть способ для многих переменных при игре и слишком мало информации, чтобы дать какой-либо полезный совет. Некоторые общие рекомендации были бы использовать асинхронные методы в вызове базы данных, а также размер yoru conneciton pool, чтобы вы могли использовать свою пробную кепку, убедитесь, что ваши обновления используют идентификатор игрока в качестве ключа, так что вы не зашли в тупик при обновлении одной и той же записи из разных потоков ,

+0

Кстати, если все, что вы делаете, читает страницу из Интернета, анализирует ее, а затем записывает в базу данных, тогда не требуется синхронизация, потому что есть * ничего * общего. –

+0

Все предложения Ремуса - хорошие вещи. У меня была аналогичная задача, когда мне нужно было динамически дросселировать количество HTTP-соединений на сервере, и для меня лучше всего было создать очередь ожидающих потоков, а затем очистить их от очереди по мере появления слотов. Если один не удалось, он был вставлен обратно в очередь. Каждый поток называется методом обратного вызова, когда он заканчивается, который я использовал для запуска следующего потока (-ов) или запроса ошибочного потока. –

+0

вы можете установить максимальное соединение в своем приложении.config, чтобы обойти ограничения по умолчанию. –

0

Как вы определяете ID пользователя? Один из вариантов состоит в том, чтобы сегментировать все потоки, чтобы поток X имел дело с идентификаторами от 0 до N и т. Д., Как часть количества потоков, которые у вас есть.

+0

Идентификатор пользователя будет начинаться с 0 и идти после каждой выборки. – Fatal510

+0

Но можете ли вы запросить заданного пользователя, зная инкрементный идентификатор? Если да, сделайте это, как я описал. –

Смежные вопросы