2012-05-06 47 views
2
的陣列

我創建多線程應用程序,它會創建一個類的TThread的動態數組,但對我的奧祕,就在於它會導致一個錯誤「訪問衝突」到「創造」訪問衝突上創建的TThread

代碼形式:

Unit UNT_Main; 

Interface 

Uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, UNT_Socks; 

Type 
    TFRM_Main = Class(TForm) 
    Procedure FormCreate(Sender: TObject); 
    Private 
    Procedure OnUpload(Success: Boolean; SockAction: TSockAction); 
    Public 
    { Public declarations } 
    End; 

Var 
    FRM_Main: TFRM_Main; 
    Socks: Array Of TSocks; 
    SA: Array Of TSockAction; 

Implementation 

{$R *.dfm} 

Procedure TFRM_Main.OnUpload(Success: Boolean; SockAction: TSockAction); 
Begin 
    ShowMessage(SockAction.Response); 
End; 

Procedure TFRM_Main.FormCreate(Sender: TObject); 
Var 
    I: Integer; 
Begin 

    SetLength(Socks, 5); 
    SetLength(SA, 5); 

    For I := 0 To High(Socks)-1 Do 
    Begin 
    SA[I].SUrl := 'http://google.com.co'; 
    Socks[I].Create(SA[I]); 
    Socks[I].OnUpload := Self.OnUpload; 
    Socks[I].Start; 
    End; 

End; 

End. 

代碼UNT_Socks:

Unit UNT_Socks; 

Interface 

Uses Classes, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP; 

// action script 
Type 
    TSockAction = Record 
    SUrl: String; 
    Response: String; 
    End; 

    // Eventos 
Type 
    // on upload event 
    TUpload = Procedure(Success: Boolean; SockAction: TSockAction) Of Object; 

    // Clase Socks, ejecuta las acciones 
Type 
    TSocks = Class(TThread) 
    // Http indy sock 
    Http: TIdHTTP; 
    // action script 
    FAtnSck: TSockAction; 
    // Temp boolean response 
    FbTempRet: Boolean; 
    Private 
    { Eventos } 
    FOnUpload: TUpload; 
    { Destructor } 
    { Metodos & Funciones } 
    Function UploadFile: Boolean; 
    { Eventos } 
    Procedure DoUpload; 
    Protected 
    Procedure Execute; Override; 
    Public 
    { Constructor } 
    Constructor Create(SockAction: TSockAction); 
    { Eventos } 
    Property OnUpload: TUpload Read FOnUpload Write FOnUpload; 
    End; 

Implementation 

{ Constructor } 
Constructor TSocks.Create(SockAction: TSockAction); 
Begin 
    Inherited Create(True); 

    FAtnSck := SockAction; // <===== Access Violation Here! 
    Http := TIdHTTP.Create(Nil); 
End; 

{ Eventos } 
Procedure TSocks.DoUpload; 
Begin 
    // check if the event is assign 
    If Assigned(FOnUpload) Then 
    // call it 
    FOnUpload(FbTempRet, FAtnSck); 
End; 

{ Execute } 
Procedure TSocks.Execute; 
Begin 

    FbTempRet := UploadFile; 
    Synchronize(DoUpload); 

End; 

Function TSocks.UploadFile: Boolean; 
Var 
    SRes: String; 
Begin 

    Try 
    With Http Do 
     FAtnSck.Response := Get(FAtnSck.SUrl); 
    Except 
    Result := False; 
    End; 

    Result := True; 
End; 

End. 

出了什麼問題?

謝謝。

+0

謝謝大家,我會按照她的意見 –

回答

9

你創建循環有2條蟲子在裏面:

1)你是循環,從而High(Socks)-1時,你應該循環,從而High(Socks)代替。您正在分配5個元素的數組,但僅對其中的4個元素進行初始化。不要在High()上使用-1,而應該使用Length()

2)您正在誤用TSocks.Create(),這就是您獲得AV的原因。您將它稱爲實例方法而不是構造函數,但尚未構建實例,從而導致崩潰。

使用這個代替:

For I := 0 To High(Socks) Do 
Begin 
    SA[I].SUrl := 'http://google.com.co'; 
    Socks[I] := TSocks.Create(SA[I]); // <-- here 
    Socks[I].OnUpload := Self.OnUpload; 
    Socks[I].Start; 
End; 
2

而不是

Socks[I].Create(SA[I]); 

你應該使用

Socks[I]:= TSocks.Create(SA[I]); 

一些小告示:

爲什麼高(襪子)-1

Uploadfile的結果是否總是爲真?

是否需要釋放Http?

+0

是的,你需要釋放的'TIdHTTP'對象當線程完成使用它。 –

1

我同意Remy.soso TSocks在UNT_Socks中有內存泄漏.Http(TIdHttp),FAtnSck(TSockAction)字段在線程終止後不是空閒的。在TSock的consturctor

集FreeOnTermiate

Constructor TSocks.Create(SockAction: TSockAction); 
Begin 
    Inherited Create(True); 
    FreeOnTerminate:=True; 
    FAtnSck := SockAction; 
    Http := TIdHTTP.Create(Nil); 
End; 

TSock

的再重寫析構函數
Destructor TSocks.Destroy; 
Begin 

    SockAction.Free; // <===== if needed 
    Http.Free; 
    Inherited; 
End; 
+1

請勿使用'FreeOnTerminate'。當您完成使用它們時明確銷燬線程對象,例如在應用程序關閉期間。 –