Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.01.15;
Скачать: [xml.tar.bz2];

Вниз

Корректное вынужденное терминирование потока.   Найти похожие ветки 

 
SergP ©   (2005-12-11 22:28) [0]

Имеется форма, где пользователь вводит данные, затем нажимает на кнопку, при этом запускается доп. поток, в котором средствами WININET отправляется запрос и закачивается контент.

Но если по каким-либо причинам (соединение с сервером происходит долго, или еще чего) пользователь не хочет ждать завершения заботы потока, и хочет закрыть форму, то как мне нужно  терминировать поток, иначе если учесть то что при закрытии форма уничтожается (free, либо action:=cafree), а доп. поток после закачки контента должен будет работать со свойствами формы, либо передавать данные в основной поток (SendMessage(FormX.Handle, .....), т.е. получается фигня..

Вобщем поток нужно терминировать и уничтожить до уничтожения формы.

Возникает вопрос: как его правильно терминировать.


procedure LoadSpend;
begin
 with TSpendThread.Create(true) do
 begin
   FreeOnTerminate:=true;
   Suspended:=false;
 end;
end;

procedure TSpendThread.Execute;
var
 s:string;
begin
 s:=OpenURL("GET",SpendRequest,SVparam.proxy);
// Здесь Либо передача s в основной поток, либо дальнейшая
//обработка. Скорее всего первое. Но это не важно, так как
//проблемы с терминированием имеют место при выполнении
//функции OpenURL, так как она может долго выполняться.

end;



Код функции OpenURL:


function OpenURL(Metod, URL:string; proxy:string="";Data:string=""; Header:string=""): string;
var
FSession, FConnect, FRequest: HINTERNET;
FMetod,FURL,Cookies:string;
BytesRead,BuffSize:cardinal;
Buff:String;
dwFlag:Cardinal;
gotIt: boolean;
URLC:TURLComponents;
tout:Integer;
HostName,UrlPath:array[1..INTERNET_MAX_PATH_LENGTH] of char;
ExtraInfo:array[1..$ffff] of char;
begin
if trim(Metod) = "" then FMetod:="GET" else FMetod:=Trim(UpperCase(Metod));
Result:="";
if pos("://",URL)= 0 then
FURL:="http://"
else FURL:="";
FURL:=FURL+URL;
FillChar(URLC,SizeOf(TURLComponents),0);
with URLC do
begin
dwStructSize := sizeOf(TURLComponents);
lpSzExtraInfo := @ExtraInfo[1];
dwExtraInfoLength := INTERNET_MAX_PATH_LENGTH;
lpSzHostName := @HostName[1];
dwHostNameLength := INTERNET_MAX_PATH_LENGTH;
lpszUrlPath := @UrlPath[1];
dwUrlPathLength := INTERNET_MAX_PATH_LENGTH;
end;
InternetCrackUrl(PChar(FURL),0,ICU_ESCAPE, URLC);
FSession := InternetOpen("Keeper", INTERNET_OPEN_TYPE_PROXY, pchar(proxy), nil, 0);
if Assigned(FSession) then
begin
  try
    tout:=10*1000;
    InternetSetOption(FSession, timeout,@tout,SizeOf(tout));
    FConnect := InternetConnect(FSession,
                                URLC.lpszHostName,
                                URLC.nPort,
                                nil,
                                nil,
                                INTERNET_SERVICE_HTTP,
                                0,
                                0);
    if Assigned(FConnect) then
      begin
        try
          if URLC.nPort = 443 then
            dwFlag := INTERNET_FLAG_SECURE
                      or INTERNET_FLAG_IGNORE_CERT_CN_INVALID
                      or INTERNET_FLAG_IGNORE_CERT_DATE_INVALID
          else
            dwFlag := 0;
          dwFlag := dwFlag or INTERNET_FLAG_RELOAD;
          StrCat(URLC.lpSzUrlPath, URLC.lpszExtraInfo);
          URLC.lpSzExtraInfo := #0;
          URLC.dwExtraInfoLength := 0;
          if FMetod = "GET" then
            begin
              if Data <> "" then
                begin
                  if pos("?", URLC.lpszUrlPath) = 0 then
                    Data:="?"+Data
                  else
                    Data:="&"+Data ;
                StrCat(URLC.lpszUrlPath,PAnsiChar(Data));
                Data:="";
               end;
             end;
          URLC.dwUrlPathLength:=length(URLC.lpszUrlPath);
          FRequest := HttpOpenRequest(FConnect, PChar(FMetod), URLC.lpszUrlPath, "HTTP/1.0",
                                      nil,
                                      nil,
                                      dwFlag,
                                      0);
          if Assigned(FRequest) then
            begin
              if pos("?", URLC.lpSzExtraInfo) = 1 then
                begin
                  inc(URLC.lpSzExtraInfo);
                  dec(URLC.dwExtraInfoLength);
                end;
              if Data <> "" then
                begin
                   URLC.lpszExtraInfo:=PAnsiChar(Data);
                   Data:="";
                end;
            URLC.dwExtraInfoLength := length(URLC.lpSzExtraInfo);
            if FMetod="POST" then
              Header:="Content-Type: application/x-www-form-urlencoded";
            if Cookies <> "" then
              begin
                if pos("Cookies: ",Cookies) = 0 then
                if Header <>"" then
                    Header:=Header+ #13#10+"Cookie: "+Cookies
                else
                    Header:="Cookie: "+Cookies ;
              end;
              try
                if HttpSendRequest(FRequest,PChar(Header), Length(Header), URLC.lpszExtraInfo, URLC.dwExtraInfoLength) then
                  begin
                    //Read file
                    BuffSize:=1024;
                    repeat
                    BytesRead:=0;
                    SetLength(buff,BuffSize);
                    gotIt := InternetReadFile(FRequest, @Buff[1], BuffSize, bytesRead);
                    Setlength(Buff,BytesRead);
                    Result:=Result+Buff;
                    until (gotIt and (bytesRead = 0));
                  end
                else
                  begin
                    Result:="#E1";
                  end;
              finally
                InternetCloseHandle(FRequest);
              end;
            end
          else
            begin

            end;
        finally
          InternetCloseHandle(FConnect);
        end;
      end
    else
      begin

      end;
  finally
    InternetCloseHandle(FSession);
  end;
end
else
begin

end;
end;


 
Verg ©   (2005-12-11 23:33) [1]


> Корректное вынужденное терминирование потока.


В таких случаях это сводится к корректному прерыванию блокирующего API вызова. Попробуй в случае необходимости закрыть главную управляющую структуру этого вызова. В данном случае - FRequest.


 
SergP ©   (2005-12-11 23:51) [2]


> Verg ©   (11.12.05 23:33) [1]
>
> > Корректное вынужденное терминирование потока.
>
>
> В таких случаях это сводится к корректному прерыванию блокирующего
> API вызова. Попробуй в случае необходимости закрыть главную
> управляющую структуру этого вызова. В данном случае - FRequest.
>


Имеется ввиду сделать  InternetCloseHandle(FRequest) из основного потока?
Так ли я понял?


 
Verg ©   (2005-12-12 09:11) [3]

Да, так.

1. Надо сделать FRequest глобальной переменной( или полем объекта)
2. Я бы ввел еще одну глоб. переменную - StopFlag : boolean;
3. Нужна крит. секция Cs.
4. Открытие :
procedure openRequest;
begin
  Cs.Enter;
  if not StopFlag then
     FRequest := HttpOpenRequest(...и т.д...);
  Cs.Leave;
end;

5. Закрывание
procedure closeRequest( Abort : boolean );
begin
  Cs.Enter;
  if FRequest <> 0 then
  begin
     InternetCloseHandle(FRequest);
     FRequest := 0;
  end;
  if Abort then
     StopFlag := true;
  Cs.Leave;
end;

6. Часть цикла чтения:
  gotIt := InternetReadFile(FRequest, @Buff[1], BuffSize, bytesRead);
  if StopFlag then break;
  И далее, там где InternetCloseHandle поменять на
  closeRequest( false)

7. Прерывание операции из другого потока:
  closeRequest( true );

Что-то в этом духе...


 
SergP ©   (2005-12-14 04:24) [4]

Вот написал, но пока не пробовал.
Просто ранее не приходилось использовать КС
Правильно ли я делаю здесь: (в первую очередь имеется ввиду создание и уничтожение КС):
(на всякий случай привожу весь код)


unit MyInet;

interface

uses Classes,WinInet,syncobjs,sysutils,messages,windows;

const
 TimeOut=10;
 WM_EVENT_ON_WORK_END=WM_USER+2;

type TNEWorkEnd=procedure(Str:string;ErrorCode:integer);

type TLoadHttp = class(TThread)
 public
   FWorkEnd:TNEWorkEnd;
   constructor OpenUrl(UserAgent, Method, URL:string;proxy:string="";Data:string=""; Header:string="");
   destructor Destroy; override;
   procedure Start;
   procedure Abort;
 private
   cs:TCriticalSection;
   FSession, FConnect, FRequest: HINTERNET;
   VFUserAgent,VFMethod,VFURL,VFProxy,VFData,VFHeader:string;
   StopFlag:boolean;
   procedure CloseRequest(Abort:boolean);
   procedure Event_on_end_work(var M : TMessage); message WM_EVENT_ON_WORK_END;
 protected
   procedure Execute; override;
end;

implementation

constructor TLoadHttp.OpenUrl(UserAgent, Method, URL:string;proxy:string="";Data:string=""; Header:string="");
begin
 create(true);
 VFUserAgent:=UserAgent;
 VFMethod:=Method;
 VFURL:=URL;
 VFProxy:=Proxy;
 VFData:=Data;
 VFHeader:=Header;
 FWorkEnd:=nil;
 StopFlag:=false;
 cs:=TCriticalSection.Create;
 FreeOnTerminate:=true;
end;

procedure TLoadHttp.Start;
begin
 Suspended:=false;
end;

destructor TLoadHttp.Destroy;
begin
 cs.Free;
 inherited Destroy;
end;

procedure TLoadHttp.Event_on_end_work(var M : TMessage);
begin
 if assigned(FWorkEnd) then FWorkEnd(String(M.WParam),M.WParam);
end;

procedure TLoadHttp.CloseRequest( Abort : boolean );
begin
 Cs.Enter;
 if FRequest<>nil then
 begin
    InternetCloseHandle(FRequest);
    FRequest := nil;
 end;
 if Abort then StopFlag := true;
 Cs.Leave;
end;

procedure TLoadHttp.Abort;
begin
 CloseRequest(true);
end;

procedure TLoadHttp.Execute;
var
FMetod,FURL,Cookies:string;
BytesRead,BuffSize:cardinal;
Buff:String;
dwFlag:Cardinal;
gotIt: boolean;
URLC:TURLComponents;
tout:Integer;
HostName,UrlPath:array[1..INTERNET_MAX_PATH_LENGTH] of char;
ExtraInfo:array[1..$ffff] of char;
Str:String;
ErrorCode:integer;
begin
 ErrorCode:=0;
 if trim(VFMethod) = "" then FMetod:="GET" else FMetod:=Trim(UpperCase(VFMethod));
 Str:="";
 if pos("://",VFURL)= 0 then FURL:="http://" else FURL:="";
 FURL:=FURL+VFURL;
 FillChar(URLC,SizeOf(TURLComponents),0);
 with URLC do
   begin
   dwStructSize := sizeOf(TURLComponents);
   lpSzExtraInfo := @ExtraInfo[1];
   dwExtraInfoLength := INTERNET_MAX_PATH_LENGTH;
   lpSzHostName := @HostName[1];
   dwHostNameLength := INTERNET_MAX_PATH_LENGTH;
   lpszUrlPath := @UrlPath[1];
   dwUrlPathLength := INTERNET_MAX_PATH_LENGTH;
 end;
 InternetCrackUrl(PChar(FURL),0,ICU_ESCAPE, URLC);
 FSession := InternetOpen(pchar(VFUserAgent), INTERNET_OPEN_TYPE_PROXY, pchar(VFproxy), nil, 0);
 if Assigned(FSession) then
   begin
   try
     tout:=10*1000;
     InternetSetOption(FSession, timeout,@tout,SizeOf(tout));
     FConnect := InternetConnect(FSession,URLC.lpszHostName,URLC.nPort,nil,nil,INTERNET_SERVICE_HTTP,0,0);
     if Assigned(FConnect) then
       begin
       try
         if URLC.nPort = 443 then dwFlag := INTERNET_FLAG_SECURE or INTERNET_FLAG_IGNORE_CERT_CN_INVALID or INTERNET_FLAG_IGNORE_CERT_DATE_INVALID else dwFlag := 0;
         dwFlag := dwFlag or INTERNET_FLAG_RELOAD;
         StrCat(URLC.lpSzUrlPath, URLC.lpszExtraInfo);
         URLC.lpSzExtraInfo := #0;
         URLC.dwExtraInfoLength := 0;
         if FMetod = "GET" then
           begin
           if VFData <> "" then
             begin
             if pos("?", URLC.lpszUrlPath) = 0 then VFData:="?"+VFData else VFData:="&"+VFData;
             StrCat(URLC.lpszUrlPath,PAnsiChar(VFData));
             VFData:="";
             end;
           end;
         URLC.dwUrlPathLength:=length(URLC.lpszUrlPath);
         Cs.Enter;
         if not StopFlag then FRequest := HttpOpenRequest(FConnect, PChar(FMetod), URLC.lpszUrlPath, "HTTP/1.0",nil,nil,dwFlag,0);
         Cs.Leave;
         if Assigned(FRequest) then
           begin
           if pos("?", URLC.lpSzExtraInfo) = 1 then
             begin
             inc(URLC.lpSzExtraInfo);
             dec(URLC.dwExtraInfoLength);
             end;
           if VFData <> "" then
             begin
             URLC.lpszExtraInfo:=PAnsiChar(VFData);
             VFData:="";
             end;
           URLC.dwExtraInfoLength := length(URLC.lpSzExtraInfo);
           if FMetod="POST" then VFHeader:="Content-Type: application/x-www-form-urlencoded";
           if Cookies <> "" then
             if pos("Cookies: ",Cookies) = 0 then
               if VFHeader <>"" then VFHeader:=VFHeader+ #13#10+"Cookie: "+Cookies else VFHeader:="Cookie: "+Cookies;

           try
             if HttpSendRequest(FRequest,PChar(VFHeader), Length(VFHeader), URLC.lpszExtraInfo, URLC.dwExtraInfoLength) then
               begin
               //Read file
               BuffSize:=1024;
               repeat
                 BytesRead:=0;
                 SetLength(buff,BuffSize);
                 gotIt := InternetReadFile(FRequest, @Buff[1], BuffSize, bytesRead);
                 if StopFlag then break;
                 Setlength(Buff,BytesRead);
                 Str:=Str+Buff;
               until (gotIt and (bytesRead = 0));
               end else ErrorCode:=ErrorCode or 1;
           finally
             CloseRequest(false);
           end;
           end else ErrorCode:=ErrorCode or 2;
       finally
         InternetCloseHandle(FConnect);
       end;
       end else ErrorCode:=ErrorCode or 4;
   finally
     InternetCloseHandle(FSession);
   end;
   end else ErrorCode:=ErrorCode or 8;
 if StopFlag then ErrorCode:=16;
 SendMessage(Handle, WM_EVENT_ON_WORK_END, ErrorCode, Integer(str));
end;
end.



Страницы: 1 вся ветка

Форум: "Основная";
Текущий архив: 2006.01.15;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.012 c
14-1134722550
Daria
2005-12-16 11:42
2006.01.15
telnet


14-1135245152
pavel_guzhanov
2005-12-22 12:52
2006.01.15
Как возвести число а дробную степень?


14-1134838711
Катерина
2005-12-17 19:58
2006.01.15
RichEdit


2-1134550192
uzver.exe
2005-12-14 11:49
2006.01.15
Помогите решить плиз...


14-1135090683
Vlad Oshin
2005-12-20 17:58
2006.01.15
Рассказ. Забавный случай.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский