Je veux executer des thread de la manière suivante :
Code du Thread :
TFusion_Base = class(TThread)
private
// Déclarations privées
Base_nu : Integer;
Mire_PP : Integer;
Nb_Lecture : Integer;
Nb_El : Integer;
Erreur_Flag : Byte;
Table_PP : String;
// Passage paramètres
Pp : Integer;
Table_Name_Inf: String;
Erreur: Byte;
protected
procedure Execute; override;
Procedure Fusion_Execute;
Procedure Affichage_Infos_Thread;
Public
constructor Create(Base_Nu_: Integer);
end;
var
Tb_Thread_Fusion_Base: Array[1..255] Of TFusion_Base;
Execution du thread :
// Lance les Threads
For i:= 1 To Max_mere Do
Begin
Tb_Thread_Fusion_Base[i]:= TFusion_Base.Create(i); // Sert à passer une variable Base_Nu
Message_Info('Thread '+IntToStr(i)+' lancé');
Application.ProcessMessages;
End;
// Boucle d'attente
Fini:= False;
while Fini= False do
begin
For i:= 1 To Max_mere Do
Begin
If (Tb_Thread_Fusion_Base[i]<> Nil)
and (Tb_Thread_Fusion_Base[i].Terminated= False)
Then
Begin
Break;
End;
If (i= Max_Mere) Then Fini:= True;
End;
Sleep(50);
Application.ProcessMessages;
end;
Problème :
Si j'ai plusieurs threads en même temps, tout s'arréte, si je n'ai qu'un seul thread cela fonctionne.
Quelqu'un a t'il rencontré ce problème ?
Code Complet du Thread :
// Thread de fusion pas Base de donnée------------------------------------------
constructor TFusion_Base.Create(Base_Nu_: Integer);
begin
Base_nu:= Base_Nu_;
inherited Create(False);
end;
Procedure TFusion_Base.Execute;
Begin
Application.ProcessMessages;
Fusion_Execute;
Application.ProcessMessages;
End;
Procedure TFusion_Base.Affichage_Infos_Thread;
Var
Aff_x: Double;
Aff_X_Int: Integer;
Aff_Affiche: Boolean;
Begin
with Fn_Fusion_Base do
begin
Canvas.Lock;
Aff_Affiche:= False;
If Tb_Base[Base_Nu].Nb_El>0 Then
Aff_x:= (Tb_Base[Base_Nu].Nb_Lecture/ Tb_Base[Base_Nu].Nb_El)*100
Else
Aff_x:=0;
Aff_X_Int:= FloatToInt(Aff_x);
// Erreur
If (Tb_Base[Base_Nu].Erreur=0) And (Tb_Base[Base_Nu].Erreur_Infos=1) Then
Begin
Tb_Base[Base_nu].Label_Erreur.Caption:='*';
Tb_Base[Base_nu].Label_Erreur.Font.Color:= clRed;
Tb_Base[Base_Nu].Erreur:=1;
Aff_Affiche:= True;
End;
// Zone Table
If Tb_Base[Base_Nu].Table_PP<> Tb_Base[Base_Nu].Table_Pp_Infos Then
Begin
Tb_Base[Base_Nu].Table_PP:= Tb_Base[Base_Nu].Table_Pp_Infos;
Tb_Base[Base_nu].Label_Table.Caption:=Tb_Base[Base_Nu].Table_Pp_Infos;
Aff_Affiche:= True;
End;
// Zone Mire
If Tb_Base[Base_Nu].Mire_PP<> Aff_X_Int Then
Begin
Tb_Base[Base_Nu].Mire_PP:= Aff_X_Int;
Tb_Base[Base_nu].Pb.Position:= Aff_X_Int;
Aff_Affiche:= True;
End;
If Aff_Affiche= True Then
Application.ProcessMessages;
Canvas.Unlock;
end;
End;
Procedure TFusion_Base.Fusion_Execute;
Var
Cpt_Table: Integer;
Table_Mere, Table_Mere_Aff: String;
i, u, Nb_El_Table_Inter_, Nb_Insert: Integer;
Table_Inter_: Array[1..255] Of Tb_Inter;
Sql_, Memo_Sql: AnsiString;
x, Erreur: Byte;
File_Name_Erreur: String;
Aff_x: Double;
Aff_X_Int: Integer;
Procedure Sqll_Add(Champs, sql_: String);
Begin
// Elimine les nuls
with Tb_Base[Base_Nu].Fn_Dm_Source.Q_Source do
If FindField(Champs).IsNull Then Exit;
If u=0 Then
Memo_Sql:= Memo_Sql+Sql_+#10
Else
Memo_Sql:= Memo_Sql+', '+Sql_+#10;
Inc(u);
End;
Procedure Write_Erreur(Const Sql_Text: AnsiString);
Var
f: TextFile;
fich: String;
Begin
fich:= Repertoire_Poubelle+'\'+File_Name_Erreur;
AssignFile(f, fich);
If FileExists(Fich)= True Then
Append(f)
Else
Rewrite(f);
Writeln(f, 'Le '+DateToStr(Date)+' à '+TimeToStr(Time)+' -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+');
Writeln(f, Sql_Text);
Flush(f);
CloseFile(f);
End;
Begin
//
Try
Tb_Base[Base_Nu].Erreur:= 0;
Tb_Base[Base_Nu].Erreur_Infos:=0;
Tb_Base[Base_Nu].Mire_PP:= 0;
Tb_Base[Base_Nu].Nb_El:= 0;
Tb_Base[Base_Nu].Table_PP:='';
File_Name_Erreur:= Tb_Base[Base_Nu].Titre+'.txt';
// Ouverture de la base Cible
with Tb_Base[Base_Nu].Fn_Dm_Source.Db_Cible do
begin
If Connected= True Then Connected:= False;
DatabaseName:= Tb_Base[0].Host+Tb_Base[0].Base;
Params.Text:= Base_Params;
Try
Connected:= True;
Except
Write_Erreur(DatabaseName);
Exit;
End;
end;
// Ouverture de la base Source
If Base_Source_Open(Base_Nu)= False Then Exit;
// Boucle pincipale du Thread
While Not Terminated Do
Begin
Nb_Insert:= 0;
For Cpt_Table:= 1 To Max_Table Do // Boucle par Table Mère**************
Begin
Table_Mere:= Tb_Table[Cpt_Table];
Table_Mere_Aff:= Table_Mere+' '+IntToStr(Cpt_Table)+'/'+IntToStr(Max_Table);
Nb_Lecture:= 0;
Mire_PP:= 0;
Table_PP:='';
Tb_Base[Base_Nu].Mire_PP:= 0;
Tb_Base[Base_Nu].Nb_El:= 0;
Tb_Base[Base_Nu].Table_PP:='';
Tb_Base[Base_Nu].Nb_Lecture:= 0;
// Requète pour connaitre le Nb d'éléments
with Tb_Base[Base_Nu].Fn_Dm_Source.Q_Source do
begin
// Affichage
Table_Name_Inf:= Table_Mere_Aff+' (Count)';
Tb_Base[Base_Nu].Table_Pp_Infos:= Table_Name_Inf;
Synchronize(Affichage_Infos_Thread);
If Active= True Then Close;
Sql.Clear;
Sql.add('Select Count(*) As Nb From '+Table_Mere);
Try
Open;
Except
Erreur:= 1;
Tb_Base[Base_Nu].Erreur_Infos:= 1;
Write_Erreur(Sql.Text);
Continue;
End;
If Eof= False Then
Nb_El:= FieldByName('Nb').asInteger
Else
Nb_El:=0;
Tb_Base[Base_Nu].Nb_El:= Nb_El;
Close;
// Affichage
Table_Name_Inf:= Table_Mere_Aff+' (R)';
Tb_Base[Base_Nu].Table_Pp_Infos:= Table_Name_Inf;
Synchronize(Affichage_Infos_Thread);
// Requéte principale
Sql.Clear;
Sql.add('Select * From '+Table_Mere);
Try
Open;
Except
Erreur:= 1;
Tb_Base[Base_Nu].Erreur_Infos:= 1;
Write_Erreur(Sql.Text);
Continue;
End;
// Analyse les champs-----------------------------------------------------------------------
Nb_El_Table_Inter_:= 0;
For i:=0 to (FieldCount-1) Do
Begin
Inc(Nb_El_Table_Inter_);
Table_Inter_[Nb_El_Table_Inter_].Nom_Inter:=Fields[i].FieldName;
Table_Inter_[Nb_El_Table_Inter_].Type_Field:=Fields[i].DataType;
Table_Inter_[Nb_El_Table_Inter_].Type_Ch_Inter:=Type_Champs_Inter(Fields[i].DataType);
Table_Inter_[Nb_El_Table_Inter_].Taille_Inter:=Fields[i].Size;
If Fields[i].IsIndexField=True Then
Table_Inter_[Nb_El_Table_Inter_].Cle_Inter:='*'
Else
Table_Inter_[Nb_El_Table_Inter_].Cle_Inter:='';
End;
// Analyse les champs-----------------------------------------------------------------------
// Boucle de transfert de Base*-*-**-*-**-*-**-*-**-*-**-*-**-*-*
while Eof= False do
begin
// Compteur
Inc(Nb_Lecture);
Tb_Base[Base_Nu].Nb_Lecture:= Nb_Lecture;
// Affichage
Table_Name_Inf:= Table_Mere_Aff;
Tb_Base[Base_Nu].Table_Pp_Infos:= Table_Name_Inf;
If Tb_Base[Base_Nu].Nb_El>0 Then
Aff_x:= (Tb_Base[Base_Nu].Nb_Lecture/ Tb_Base[Base_Nu].Nb_El)*100
Else
Aff_x:=0;
Aff_X_Int:= FloatToInt(Aff_x);
// Zone Mire
If Tb_Base[Base_Nu].Mire_PP<> Aff_X_Int Then
Synchronize(Affichage_Infos_Thread);
// Génération du Sql----------------------------------------
Memo_Sql:= 'Insert into '+Table_Mere+' ('+#10;
// Champs
u:=0;
For i:= 1 To Nb_El_Table_Inter_ Do
Begin
x:= Type_Champs_Byte(Table_Inter_[i].Type_Field);
{Retourne le type du champs
0 Integer
1 String
2 Memo
3 Float
4 Date
}
Case x Of
0..3: Sqll_Add( Table_Inter_[i].Nom_Inter, Table_Inter_[i].Nom_Inter);
4: If FieldByName(Table_Inter_[i].Nom_Inter).asString<>'' Then
Sqll_Add( Table_Inter_[i].Nom_Inter, Table_Inter_[i].Nom_Inter);
End;
End;
Memo_Sql:= Memo_Sql+') Values ('+#10;
// Valeurs
u:=0;
For i:= 1 To Nb_El_Table_Inter_ Do
Begin
x:= Type_Champs_Byte(Table_Inter_[i].Type_Field);
{Retourne le type du champs
0 Integer
1 String
2 Memo
3 Float
4 Date
}
Case x Of
0: Sqll_Add( Table_Inter_[i].Nom_Inter, IntegerToStr(FieldByName(Table_Inter_[i].Nom_Inter).asInteger) );
1..2: Sqll_Add( Table_Inter_[i].Nom_Inter, Ct+ FieldByName(Table_Inter_[i].Nom_Inter).asString+ Ct );
3: Sqll_Add( Table_Inter_[i].Nom_Inter, FormatFloat('0.00',Decimal2(FieldByName(Table_Inter_[i].Nom_Inter).asFloat)) ) ;
4: If FieldByName(Table_Inter_[i].Nom_Inter).asString<>'' Then
Sqll_Add( Table_Inter_[i].Nom_Inter, Ct+ Sql_Date(FieldByName(Table_Inter_[i].Nom_Inter).asString)+ Ct );
End;
End;
Memo_Sql:= Memo_Sql+');';
// Génération du Sql----------------------------------------
// Execute le SQL dans la Base Cible------------------------
with Tb_Base[Base_Nu].Fn_Dm_Source.IBSQL_Cible do
begin
If Transaction.InTransaction= False Then
Transaction.StartTransaction;
If Open Then Close;
Sql.Clear;
Sql.Text:= Memo_Sql;
Try
ExecQuery;
Inc(Nb_Insert); // Compteur d'insertion
Except
//
Tb_Base[Base_Nu].Fn_Dm_Source.Q_Source.Next;
Write_Erreur(Sql.Text);
Tb_Base[Base_Nu].Erreur_Infos:= 1;
Erreur:= 1;
Continue;
End;
If Nb_Insert> 3000 Then
Begin
// Affichage
Table_Name_Inf:= 'Commit';
Tb_Base[Base_Nu].Table_Pp_Infos:= Table_Name_Inf;
Synchronize(Affichage_Infos_Thread);
If Transaction.InTransaction= True Then
Transaction.Commit;
Nb_Insert:= 0;
End;
end;
// Execute le SQL dans la Base Cible------------------------
Application.ProcessMessages;
Next; // Suivant
end;
Close;
// Boucle de transfert de Base*-*-**-*-**-*-**-*-**-*-**-*-**-*-*
end;
End; // Boucle par Table Mère********************************************
// Fermeture des transactions
with Tb_Base[Base_Nu].Fn_Dm_Source.Q_Source do
begin
If Transaction.InTransaction= True Then
Transaction.Commit;
end;
with Tb_Base[Base_Nu].Fn_Dm_Source.IBSQL_Cible do
begin
Table_Name_Inf:= 'Commit';
Tb_Base[Base_Nu].Table_Pp_Infos:= Table_Name_Inf;
Synchronize(Affichage_Infos_Thread);
If Transaction.InTransaction= True Then
Transaction.Commit;
end;
// Fermeture des Bases de données
with Tb_Base[Base_Nu].Fn_Dm_Source.Db_Source do
begin
Connected:= False;
end;
with Tb_Base[Base_Nu].Fn_Dm_Source.Db_Cible do
begin
Table_Name_Inf:= 'Terminé !';
Tb_Base[Base_Nu].Table_Pp_Infos:= Table_Name_Inf;
Synchronize(Affichage_Infos_Thread);
Connected:= False;
end;
Terminate; // Terminé
Break;
end;
// Boucle pincipale du Thread
Except
Terminate; // Terminé avec erreur !
End;
End;
// Thread de fusion pas Base de donnée------------------------------------------
Partager