Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / HttpWebRequest + Threading / 16 сообщений из 16, страница 1 из 1
20.09.2004, 02:18
    #32701436
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Пишу одну программку. Она сканирует некий сайт, парсит хтмл и сохраняет результаты в xml.
Столкнулся со следующей проблемой:Надо было сделать ее многопотоковой - она сканирует на сайте несколько категорий, у каждой категории есть некоторое количество страниц.
Само сканирование выглядит примерно так:

.................
HttpWebRequest rq = (HttpWebRequest)HttpWebRequest.Create(sURL);
StreamReader rdr = new StreamReader(rq.GetResponse().GetResponseStream());

string result = rdr.ReadToEnd();
......... обрабатываем результат ........

Все работает, но....
я надеялся, что многопотоковость даст мне выигрыш в производительности, а вышло наоборот :)
Результаты работы с разным количеством потоков:
10 потоков : 1 минута 33 секунды
5 потоков : 1 минута 4 секунды
1 поток : 1 минута 8 секунд.

Причем чем больше потоков, тем медленнее работают именно эти три строчки...Кто-нибудь знает, как это исправить?
...
Рейтинг: 0 / 0
20.09.2004, 10:01
    #32701597
ziktuw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Сессию выруби. Наличие сессии заставляет web-сервер упорядочивать все обращения одной сессии.

--------------
Свет в конце тонеля временно потушен по техническим причинам.
...
Рейтинг: 0 / 0
20.09.2004, 10:29
    #32701649
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
А как?
...
Рейтинг: 0 / 0
20.09.2004, 17:27
    #32702922
ziktuw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Например, так:

<%@ Language=C# EnableSessionState=false %>

в начале соответствующей странички

--------------
Свет в конце тонеля временно потушен по техническим причинам.
...
Рейтинг: 0 / 0
20.09.2004, 17:47
    #32702964
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Стоп. У меня WinForms приложение. И из него я делаю запросы....
...
Рейтинг: 0 / 0
21.09.2004, 14:30
    #32704351
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Так. Более детальное описание вопроса:
Создаю 10 HttpWebRequest к одному и тому же url.
Если их запускать в параллельных потоках, то такое ощущение, что они выстраиваются в некую очередь, т.е. в 10 тредах в первом запрос выполняется за секунду, во втором за 2, и так далее.
Если я запущу одновременно две разные программы, делающие такой запрос, они выполняются обе за одну секунду.
Сейчас я вышел из положения таким образом: я создаю отдельный AppDomain для каждого треда, и тогда все запросы выполняются параллельно, с нормальной скоростью.
Вопрос: Можно ли как то сделать так, чтобы запросы к одному серверу внутри одного домена приложений в разных потоках выполнялись параллельно а не последовательно?
...
Рейтинг: 0 / 0
21.09.2004, 15:45
    #32704616
ziktuw
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Надо как-то запретить cookie. Тогда веб-сервер не будет знать, что разные обращения из одного источника.


Код: plaintext
1.
2.
 
_________
Свет в конце тоннеля временно потушен по техническим причинам. 
...
Рейтинг: 0 / 0
21.09.2004, 16:21
    #32704727
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
В HttpWebRequest ты сам задаешь куки,а я ничего такого не передаю, так что это не поможет...
Это наверное реализация самого класса такая... Кстати пробовал через винапи (WinInet.dll) - та же фигня. И на дотнете и на неуправляемом коде...
Вопрос все еще открыт. :)
...
Рейтинг: 0 / 0
21.09.2004, 18:00
    #32705009
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Максим РуденкоТак. Более детальное описание вопроса:
Создаю 10 HttpWebRequest к одному и тому же url.
Если их запускать в параллельных потоках, то такое ощущение, что они выстраиваются в некую очередь, т.е. в 10 тредах в первом запрос выполняется за секунду, во втором за 2, и так далее.


Все правильно. Не более 2 одновременных запросов к одному и тому же URI. Что бы поправить ситуацию надо внимательно почитать msdn по классу WebRequest в начале программы установить максимальное количество одновременных соединений:

Код: plaintext
1.
2.
     // Для десяти тредов, соответственно, десять одновременных соединений 
    ServicePointManager.DefaultConnectionLimit = 10;

--
WBR, Roman S. Golubin
ICQ UIN:63253392
...
Рейтинг: 0 / 0
21.09.2004, 19:31
    #32705168
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Не знаю, где я неправ, но ничего не поменялось.
С несколькими AppDomain работает на порядок быстрее....
...
Рейтинг: 0 / 0
22.09.2004, 21:24
    #32707590
EvAlex
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Roman S. GolubinВсе правильно. Не более 2 одновременных запросов к одному и тому же URI.

к одному и тому же сайту.

Я делал подобную вещь, которая подбирала пароли к destinysphere.ru
Но пошёл другим путём.
Сделал web-service который сканирует сайт
и client, который к этому web-service создавал асинхронные запросы.
Скорость работы была просто поразительна.
...
Рейтинг: 0 / 0
28.09.2004, 19:13
    #32715498
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
WebService мне делать нельзя к сожалению... Я выкрутился по-другому, я вместо HttpWebRequest использую TcpClient. Скорость тоже поразительная :).
Кстати перепробовал кучу способов, но заставить HttpWebRequest делать больше 2х подключений у меня так и не вышло.....
Если кто-нибудь покажет _работающий_ кусочек кода, буду безумно признателен.
...
Рейтинг: 0 / 0
29.09.2004, 12:17
    #32716294
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Максим РуденкоWebService мне делать нельзя к сожалению... Я выкрутился по-другому, я вместо HttpWebRequest использую TcpClient. Скорость тоже поразительная :).
Кстати перепробовал кучу способов, но заставить HttpWebRequest делать больше 2х подключений у меня так и не вышло.....
Если кто-нибудь покажет _работающий_ кусочек кода, буду безумно признателен.

Смотри кусочек :

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
class HttpWebRequestMultyThreading
{
  static Encoding encoding = Encoding.GetEncoding(1251);

  class RequestState
  {
    public const int BUFFER_SIZE = 1024;
    public byte[] bufferRead;
    public StringBuilder requestData;
    public WebRequest request;
    public WebResponse response;
    public Stream responseStream;
    public RequestState()
    {
      bufferRead = new byte[BUFFER_SIZE];
      requestData = new StringBuilder("");
      request = null;
      responseStream = null;
    }
  }

  [STAThread]
  static void Main(string[] args)
  {
    ServicePointManager.DefaultConnectionLimit = 10;

    Thread[] threads = new Thread[10];

    for (int i = 0; i < 10; i++)
    {
      threads = new Thread(new ThreadStart(RequestThread));
    }
    for (int i = 0; i < 10; i++)
    {
      threads[i].Start();
    }

    Thread.Sleep(20000);
  }

  private static void RequestThread()
  {
      HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.microsoft.com");
      RequestState state = new RequestState();
      state.request = request;
      IAsyncResult asyncResult = request.BeginGetResponse(new AsyncCallback(RespCallback), state);
      Console.WriteLine("{0}", request.ServicePoint.CurrentConnections);
    }

    private static void RespCallback(IAsyncResult asyncResult)
    {
      RequestState state = (RequestState) asyncResult.AsyncState;
      WebRequest  request = state.request;
      state.response =  request.EndGetResponse(asyncResult);
      state.responseStream = state.response.GetResponseStream();

      IAsyncResult asynchronousResultRead = state.responseStream.BeginRead(state.bufferRead, 0, RequestState.BUFFER_SIZE, new AsyncCallback(ReadCallBack), state);
    }

    private static void ReadCallBack(IAsyncResult asyncResult)
    {
      RequestState state = (RequestState) asyncResult.AsyncState;
      Stream responseStream = state.responseStream;
      int read = responseStream.EndRead(asyncResult);

      if (read > 0)
      {
        state.requestData.Append(encoding.GetString(state.bufferRead, 0, read));
        asyncResult = responseStream.BeginRead(state.bufferRead, 0, RequestState.BUFFER_SIZE, new AsyncCallback(ReadCallBack), state);
      }
      else
      {
        Console.WriteLine("ready");
         [i]// Здесь вызов обработчика результатов 
         // ResulParser(state.requestData.ToString()); 
      }

    }
}
...
Рейтинг: 0 / 0
06.10.2004, 13:34
    #32725856
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Вот, немножко поменял код, чтобы замерить время выполнения каждого треда:
using System;
using System.Text;
using System.Net;
using System.Threading;
using System.IO;

class HttpWebRequestMultyThreading
{
static Encoding encoding = Encoding.GetEncoding(1251);

class RequestState
{
public const int BUFFER_SIZE = 1024;
public byte[] bufferRead;
public StringBuilder requestData;
public WebRequest request;
public WebResponse response;
public Stream responseStream;
public RequestState()
{
bufferRead = new byte[BUFFER_SIZE];
requestData = new StringBuilder("");
request = null;
responseStream = null;
}
}
private static DateTime start_time;

[STAThread]
static void Main(string[] args)
{
ServicePointManager.DefaultConnectionLimit = 10;

Thread[] threads = new Thread[10];

for (int i = 0; i < 10; i++)
{
threads = new Thread(new ThreadStart(RequestThread));
}
start_time = DateTime.Now;
for (int i = 0; i < 10; i++)
{
threads.Start();
}

Thread.Sleep(20000);
Console.ReadLine();
}

private static void RequestThread()
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://www.bigmir.net");
RequestState state = new RequestState();
state.request = request;
IAsyncResult asyncResult = request.BeginGetResponse(new AsyncCallback(RespCallback), state);
Console.WriteLine("{0}", request.ServicePoint.CurrentConnections);
}

private static void RespCallback(IAsyncResult asyncResult)
{
RequestState state = (RequestState) asyncResult.AsyncState;
WebRequest request = state.request;
state.response = request.EndGetResponse(asyncResult);
state.responseStream = state.response.GetResponseStream();

IAsyncResult asynchronousResultRead = state.responseStream.BeginRead(state.bufferRead, 0, RequestState.BUFFER_SIZE, new AsyncCallback(ReadCallBack), state);
}

private static void ReadCallBack(IAsyncResult asyncResult)
{
RequestState state = (RequestState) asyncResult.AsyncState;
Stream responseStream = state.responseStream;
int read = responseStream.EndRead(asyncResult);

if (read > 0)
{
state.requestData.Append(encoding.GetString(state.bufferRead, 0, read));
asyncResult = responseStream.BeginRead(state.bufferRead, 0, RequestState.BUFFER_SIZE, new AsyncCallback(ReadCallBack), state);
}
else
{
TimeSpan t = DateTime.Now - start_time;
Console.WriteLine(t.ToString());

// Здесь вызов обработчика результатов
// ResulParser(state.requestData.ToString());
}

}
}


Результат:

1
10
3
2
9
7
4
5
6
8
00:00:01.9374876
00:00:02.5468587
00:00:03.4999776
00:00:04.8905937
00:00:04.9218435
00:00:04.9530933
00:00:05.1249672
00:00:05.4843399
00:00:05.6562138
00:00:07.3280781

Как видно - время выполнения растет....
Когда я использую сокеты - все треды выполняются за примерно одинаковое время, и c увеличением количества тредов не растет.
Задачу-то я уже решил, но вышло (как мне кажется) не очень элегантно - я ведь не писал полностью реализацию протокола HTTP, только основные кусочки...Не могу например работать с HTTPS, и все такое...Поэтому мне все еще интересно как заставить работать HttpWebRequest, или найти реализацию HTTP на C#...
...
Рейтинг: 0 / 0
06.10.2004, 14:54
    #32726087
Roman S. Golubin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Максим Руденко
Результат:

00:00:01.9374876
00:00:02.5468587
00:00:03.4999776
00:00:04.8905937
00:00:04.9218435
00:00:04.9530933
00:00:05.1249672
00:00:05.4843399
00:00:05.6562138
00:00:07.3280781

Как видно - время выполнения растет....
Когда я использую сокеты - все треды выполняются за примерно одинаковое время, и c увеличением количества тредов не растет.
Задачу-то я уже решил, но вышло (как мне кажется) не очень элегантно - я ведь не писал полностью реализацию протокола HTTP, только основные кусочки...Не могу например работать с HTTPS, и все такое...Поэтому мне все еще интересно как заставить работать HttpWebRequest, или найти реализацию HTTP на C#...

У меня тот же код к серверу в локальной сетке (инет у меня слишком медленен для таких измерений) ходит так (100 коннектов одновременно):

00:00:01.0312500
00:00:01.0312500
00:00:01.0312500
00:00:01.0468750
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0625000
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0468750
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0781250
00:00:01.0937500
00:00:01.4062500
00:00:01.4062500
00:00:01.4062500
00:00:01.4062500
00:00:01.4062500
00:00:01.4062500
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4218750
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4375000
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4531250
00:00:01.4687500
00:00:01.4687500
00:00:01.4687500
00:00:01.4687500
00:00:01.4687500
00:00:01.4687500

Как видно, время работы не очень сильно зависит от количества одновременных коннектов, хотя и растет. Ну а то что разброс больше чем у просто сокетов, вероятно зависит как раз от того чего ты хочешь - наличия https и прочих наворотов.
...
Рейтинг: 0 / 0
06.10.2004, 17:16
    #32726566
Максим Руденко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
HttpWebRequest + Threading
Локалка не показатель - сам на это напоролся :)
Когда начинаешь подключаться куда-то на мир, время растет в разы....
И я не думаю что это зависит от реализации поддержки HTTPS и прочего...
Все таки дело именно в подключении...
Ну ладно, отложу на будущее - может когда то и решится,
всем спасибо :)
...
Рейтинг: 0 / 0
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / HttpWebRequest + Threading / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]