Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 04.01.2013, 14:52   #1
RelictOs
Новичок
Джуниор
 
Регистрация: 26.02.2012
Сообщений: 2
Вопрос Многопоточная загрузка

Всем привет!
Недавно меня посетила идея написать нечто вроде многопоточного загрузщика файлов. Такие данные, как размер, скорость и главное состояние загрузки я решил выводить в TNextGrid (аналог TStringGrid с расширенными возможностями вроде колонок-прогрессбаров).
Как я уже сказал, концепция программы предполагает многопоточность, которую в целом и общем я реализовал. Но есть одно но (точнее даже 2).

Начну с первого и главного - при загрузке нескольких файлов одновременно они загружаются не одновременно, а по очереди.
Код выполнения потока:
Код:
procedure TDownloadThread.Execute;
var
  hInet,  //соединение
  hURL: HINtERNET;    //ссылка на файл
  BufArr: array[1..1024] of byte; //буфер, в который будем скачивать
  BufLen: DWORD;
  sFile: file; //наш файл
  i: integer;
begin
  hInet := InternetOpen(PChar(Application.ExeName),INTERNET_OPEN_TYPE_PrECONFIG,nil,nil,0); //открываем соединение

  for i := 0 to Length(filelist)-1 do  //где filelist - чтото вроде набора файлов для скачивания
    begin
      hURL := InternetOpenURL(hInet,PAnsiChar(filelist[i].url),nil,0,0,0);
      if FileExists(fclientpath+'\'+filelist[i].folder) then
        DeleteFile(fclientpath+'\'+filelist[i].folder);
      AssignFile(sFile,fclientpath+'\'+filelist[i].folder);
      Rewrite(sFile,1);

      repeat
        InternetReadFile(hURL,@BufArr,Sizeof(BufArr),BufLen);
        downloaded := downloaded+ BufLen;
        BlockWrite(sFile,BufArr,BufLen);
        Synchronize(showprogress);
      until BufLen=0;
      CloseFile(sFile);
      hURL := 0;
    end;
  InternetCloseHandle(hInet); //закрываем соединение
end;

//и процедура вывода ShowProgress
procedure TDownloadThread.ShowProgress;
begin
  fGrid.Cell[3,frow].AsInteger := round(downloaded/totalsize*100); //fGrid - указатель на наш NextGrid; Downloaded - сколько загруженно
  //a TotalSize - размер всех всех файлов в списке, который вычисляется еще до Execute
  Application.ProcessMessages;
end;
Надеюсь, в коде все понятно прокомментировано, и проблема лишь в моей невнимательности или глупости
С нетерпением жду ответов


Теперь вторая проблема - очень хотелось бы реализовать паузу при загрузке, но и это оказалось не так просто.
Поскольку Suspend в данном случае (насколько я понял) не лучший метод (хотя и он не работает), я решил сделать это через булевскую переменную.
Проблема же в том, что при вызове функции возникает AccessViolation, и я понятия не имею почему и что с ним делать.

Код создания потока и собственно паузы:

Код:
constructor TDownloadThread.Create(list: TXMLDocument; var Grid: TNextGrid; row: integer; clientpath: string);
begin
  inherited Create(true);
  FreeOnTerminate := true; //поток освобождается при завершении
  frow := row;             //id или наша строка таблицы
  fclientpath := clientpath; //папка для общей загрузки
  SetFileList(list);       //составляем список файлов для скачивания

  fEnablePause := false; //нельзя ставить поток на паузу
  fPaused := false; // переменная паузы в false

  if Length(filelist) <= 0 then  // если скачивать нечего - закрываемся
    begin
      Grid.Cell[3,frow].AsInteger := 100;
      Self.Terminate;
      exit;
    end;

  totalsize := GetTotalSize; //вычисляем полный размер файлов
  downloaded := 0; // загружено - пока 0
  fGrid := @Grid;   // присваиваем указатель на таблицу
  fGrid.Cell[5,frow].AsString := inttostr(round(totalsize/1024))+ ' KB';
end;

//и собственно функция* паузы
function TDownloadThread.Pause: boolean;
begin
  result := false;
  if (EnablePause) or (fPaused) then exit;
  fPaused := true;
  result := true;
end;
Хочу уточнить, что в коде первой проблемы вы не заметите применения цикла вроде
Код:
while fPaused do
 Application.ProcessMessages;
потому что из-за изменения алгоритма загрузки(раньше использовал Indy) я ее временно убрал. Но суть проблемы не в несратываемости, а в ошибке при ее вызове из программы.
RelictOs вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
многопоточная сортировка слиянием gagarin614 Помощь студентам 0 03.10.2012 16:03
Многопоточная программа kakawkin Общие вопросы Delphi 4 05.06.2011 00:33
С++ Многопоточная обработка матрицы порядка 1000х1000 Borisov Общие вопросы C/C++ 11 10.01.2011 22:32
Загрузка ОС subbota Операционные системы общие вопросы 1 24.09.2009 14:32
Загрузка ЦП HelloZAPOR Win Api 7 05.11.2007 15:43