Форум: "Сети";
Текущий архив: 2006.01.15;
Скачать: [xml.tar.bz2];
ВнизМногопоточная закачка файлов Найти похожие ветки
← →
maVladimir (2005-09-27 20:04) [0]Здравствуйте, уважаемые кодеры.
Хотелось бы узнать, каким образом работает многопоточная закачка файлов.
То есть, конечно, есть некоторые прикидки насчет того, как это сделать, но все они мне кажутся очень некорректными путями решения этой задачи.
Интересует именно МНОГОПОТОЧНАЯ закачка файлов (дозакачка не требуется по той причине, что файлы небольшие, но их ОЧЕНЬ МНОГО).
И, если, не жалко, выложите немного кода для примера.
Заранее благодарен.
← →
S@ska (2005-09-27 22:40) [1]http://bexet.boom.ru/page/source.htm
← →
maVladimir (2005-09-28 07:46) [2]Если имелось в виду http://bexet.boom.ru/arc/src/dnload.rar, то это совсем не то, что хотелось.
Нужна МНОГОПОТОЧНАЯ закачка, то есть создание множества потоков для закачки разных файлов.
Владимир.
← →
dmitry501 © (2005-09-28 08:07) [3]maVladimir (28.09.05 7:46) [2]
Если есть процедурка закачки одного файла, то что мешает запустить ее в несколько потоков?
← →
maVladimir (2005-09-28 08:37) [4]Мешает отсутствие красивого решения.
Я хотел сделать следующим образом:
Программа выбирает из списка какой-то URL и, если количество запущенных потоков меньше максимума, то запускаем новый поток, который тянет этот URL. В список (TList) запихиваем ссылку на этот поток. Затем после закачки страницы поток передает сообщение основному потоку о том, что страница скачана. Здесь облом! Необходимо из списка потоков удалить ссылку на освобожденный поток, но совершенно непонятно, как узнать, когда уже МОЖНО удалять ее. То есть после закачки поток посылает сообщение и сразу же terminate. Выходит, что потока уже нет, а ссылка в списке еще существует. Можно после приема сообщение от потока через какое-то время удалять его из списка (в надежде на то, что он уже завершил всю свою работу), но это неправильно.
В общем, я не знаю, что я тут понаписал, но решение это некрасивое и неправильное. Понимаю, что работать будет, но хочется узнать, как делают мастера.
Владимир.
← →
dmitry501 © (2005-09-28 09:01) [5]>Затем после закачки страницы поток передает сообщение основному потоку о том, что страница скачана.
Страница уже скачана!
>Можно после приема сообщение от потока через какое-то время удалять его из списка (в надежде на то, что он уже завершил всю свою работу), но это неправильно.
Страничка уже скачана! И ссылку можно спокойно удалять.
Это решение представляет из себя простейший диспетчер потоков и вполне красиво...
Странно как-то...
← →
maVladimir (2005-09-28 09:27) [6]я имею в виду следующее:
constructor TLoadingThread.Create(CreateSuspended: boolean);
begin
inherited Create(CreateSuspended);
FreeOnTerminate := true;
HTTP := TIdHTTP.Create;
end;
destructor TLoadingThread.Destroy;
begin
HTTP.Free;
inherited;
end;
procedure TLoadingThread.Execute;
var
Page: string;
begin
Page := HTTP.Get("bla");
Посылаем что скачано в основной поток;
end; //Здесь уже поток обращается к своему деструктору и уничтожается.
Что происходит в основном потоке? Он получает строку с содержащейся в ней скачанной страницей от потока N и ему надо удалить указатель на этот поток из MyThreadList. Так вот, когда он должен это сделать?
Сразу после получения страницы? Но тогда еще поток не освободил свою память.
Послу некоторого времени? Но откуда узнать, что поток все свои дела уже сделал?
Может быть, я, конечно, некорректно поставил вопрос и неумело объяснил его, но все же я старался.
Спасибо за внимание.
← →
Seeker © (2005-09-28 09:40) [7]
> Так вот, когда он должен это сделать?
В обработчике OnTerminate.
← →
dmitry501 © (2005-09-28 09:43) [8]А для чего Вы храните указатели на потоки? Я думал у Вас в списке просто хранятся адреса закачиваемых в данный момент файлов, чтобы их повторно не качать. Да, даже если и там хранится указатель на поток, то все-равно ждать не нужно, если после того как поток отправил сообщение, то он сразу завершается. Или Вы боитесь, что в деструкторе возникнет исключение? Тогда уберите
HTTP := TIdHTTP.Create;
из конструктора иHTTP.Free;
из деструктора и перенесите их вExecute
потока.
з.ы.
В принципе основной поток процесса и должен выполнять роль диспетчера. Т.е. из кокого-то листа он берет адрес очередного файла для закачки и запускает дополнительный поток, передав ему этот адрес для закачки. Затем этот адрес он перемещает во второй список, в котором хранятся адреса файлов, закачивающихся в данный момент. Получив от потока сообщение об окончании закачки файла перемещает адрес этого файла из второго списка в третий, в котором хранятся адреса уже закачанных файлов. Дополнительный поток никак не зависит от других потоков и просто закачивает файл. Все просто, логично. по вкусу можете считать сколько адресов находится во втором списке, для ограничения кол-во выполняемых потоков, а также обрабатыватьтаймауты и пр.
← →
maVladimir (2005-09-28 10:49) [9]Указатели на потоки я храню для того, чтобы suspend"ить и resume"ировать их, если это потребуется.
Да, кстати, после того, как пришло сообщение от потока о том, что страница скачана или не скачана (в случае какой-нибудь ошибки), уже можно удалять указатель на этот thread, потому что обращения к нему уже точно больше не будет. Оказывается, что можно вообще не ждать, пока поток завершит свою работу и освободит память. Как-то мне это не приходило в голову. :)
> Seeker.
Write an OnTerminate event handler to execute code after the thread finishes executing.
То есть код в OnTerminate исполняется еще до того, как поток уничтожается, а надо было наоборот.
> dmitry501
Да, кстати, с HTTP := TIdHTTP.Create и HTTP.Free лучше сделать так, как вы посоветовали. Хотя бы чисто из эстетических соображений :).
Спасибо за наведение на хорошие мысли. :)))
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2006.01.15;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.014 c