2015-10-20 5 views
0

J'ai créé un thread et cela fonctionne bien quand Preview=false, mais quand je mets Preview=true alors je reçois toujours une erreur (code d'erreur du système 5 accès refusé).Code d'erreur du système Delphi 5 accès refusé

Je veux créer un rapport car il faut plus de 10 secondes pour le générer.

Quelqu'un peut-il expliquer ce qui se passe?

procedure TReportThread1.Execute; 
begin  
    if ReportBUFFER = 1 then begin 
     dm.rmvFarm.Filename := reportpath + 'aoc.rep'; 
     dm.rmvFarm.Report.Params.Items[0].Value := Thread_StartOfTheDayR1; 
     dm.rmvFarm.Report.Params.Items[1].Value := Thread_EndOfTheDayR1; 
     dm.rmvFarm.Report.Params.Items[2].Value := currentusr; 
     dm.rmvFarm.Preview := true; 
     dm.rmvFarm.Execute; 

     ReportThread1.free; 
    end;             
end. 

Répondre

0

Si vous regardez le code source pour TVCLReport, sa méthode Execute() affiche une interface utilisateur à base VCL lorsque Preview=True:

type 
    TVCLReport=class(TCBaseReport) 
    private 
    prcontrol:TRpPreviewControl; 
    ... 
    end; 

function TVCLReport.Execute:boolean; 
var 
... 
begin 
inherited Execute; 
... 
try 
if Preview then 
begin 
    prcontrol:=TRpPreviewControl.Create(nil); 
    try 
    prcontrol.Report:=Report; 
    Result:=ShowPreview(prcontrol,Title); 
    finally 
    prcontrol.free; 
    end; 
end 
else 
begin 
    ... 
end; 

TRpPreviewControl est dérivé de TScrollBox. ShowPreview() est une fonction d'assistance qui place l'objet TRpPreviewControl sur un objet TForm personnalisé (TFRpPreview) qui est affiché avec ShowModal(). Les interfaces utilisateur basées sur la VCL ne sont pas sécurisées pour les threads et ne peuvent pas être utilisées en dehors du contexte du thread principal de l'interface utilisateur. Comme vous pouvez le voir, TVCLReport.Execute() ne vous offre aucune possibilité de synchronisation avec le thread d'interface utilisateur principal, donc Preview=True n'est PAS sûr à utiliser dans un thread de travail. Si vous souhaitez appeler TVCLReport.Execute() dans un thread de travail, mais afficher son aperçu d'une manière thread-safe, une solution possible serait d'altérer le code source pour TVCLReport pour exposer la fonctionnalité de prévisualisation d'une manière qui vous permet pour appeler à l'aide TThread.Synchronize(), par exemple:

type 
    TVCLReportPreviewEvent = procedure(Sender: TObject; var VResult: Boolean) of object; 

    TVCLReport=class(TCBaseReport) 
    private 
    prcontrol:TRpPreviewControl; 
    ... 
    public 
    OnPreview: TVCLReportPreviewEvent; 
    function DisplayPreview: Boolean; 
    end; 

function TVCLReport.Execute:boolean; 
var 
... 
begin 
    inherited Execute; 
    ... 
    try 
    if Preview then 
    begin 
    if Assigned(OnPreview) then 
     OnPreview(Self, Result) 
    else 
     Result := DisplayPreview; 
    end 
    else 
    begin 
    ... 
end; 

function TVCLReport.DisplayPreview: Boolean; 
begin 
    prcontrol:=TRpPreviewControl.Create(nil); 
    try 
    prcontrol.Report:=Report; 
    Result := ShowPreview(prcontrol, Title); 
    finally 
    prcontrol.free; 
    end; 
end; 

procedure TReportThread1.Execute; 
begin  
    if ReportBUFFER = 1 then begin 
    dm.rmvFarm.Filename := reportpath + 'aoc.rep'; 
    dm.rmvFarm.Report.Params.Items[0].Value := Thread_StartOfTheDayR1; 
    dm.rmvFarm.Report.Params.Items[1].Value := Thread_EndOfTheDayR1; 
    dm.rmvFarm.Report.Params.Items[2].Value := currentusr; 
    dm.rmvFarm.Preview := true; 
    dm.rmvFarm.OnPreview := DisplayPreviewInMainThread; 
    dm.rmvFarm.Execute; 
    ReportThread1.free; 
    end;             
end; 

procedure TReportThread1.DisplayPreviewInMainThread(Sender: TObject; var VResult: Boolean); 
begin 
    TThread.Synchronize(nil, 
    procedure 
    begin 
     VResult := dm.rmvFarm.DisplayPreview; 
    end 
); 
end; 

Bien que, si votre rapport ne prend vraiment beaucoup de temps pour générer, alors les chances sont que l'aperçu prendra également un long moment pour générer. Si oui, cette solution ne vous apportera rien d'utile. Il peut être plus simple de laisser simplement le TVCLReport dans le thread d'interface utilisateur principal et d'afficher un message à l'utilisateur pendant qu'il est en train de générer le rapport.

Vous aurez juste à l'essayer et voir ce qui se passe.

+0

Merci beaucoup pour vos efforts et vos idées. Je vous en suis reconnaissant. Je vais essayer et vous faire savoir si cela fonctionne. – ErenRavenHeart

+0

Je n'arrive pas à comprendre ... "dm.rmvFarm.DisplayPreview", "dm.rmvFarm.OnPreview" sont non déclarés .. – ErenRavenHeart

+0

@ErenRavenHeart Vous avez peut-être une autre version de Reportmanager que Remy. Ou vous n'avez pas inclus les fichiers source appropriés dans votre clause Uses. Utilisez la documentation. –