2015-10-20 3 views
0

Я создал поток, и он работает хорошо, когда Preview=false, но когда я установил Preview=true, тогда я всегда получаю сообщение об ошибке (системный код ошибки 5 доступ запрещен).Код ошибки системы Delphi 5 доступ запрещен

Я хочу вывести отчет, потому что для его создания требуется более 10 секунд.

Может ли кто-нибудь объяснить, что происходит?

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. 

ответ

0

Если вы посмотрите на исходный код для TVCLReport, его метод Execute() отображает VCL на основе пользовательского интерфейса, когда 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 является производным от TScrollBox. ShowPreview() - вспомогательная функция, которая помещает объект TRpPreviewControl в пользовательский объект TForm (TFRpPreview), который отображается с ShowModal(). Пользовательские интерфейсы на основе VCL не являются потокобезопасными и не могут использоваться вне контекста основного потока пользовательского интерфейса. Как вы можете видеть, TVCLReport.Execute() не предоставляет вам возможности синхронизации с основным потоком пользовательского интерфейса, поэтому Preview=True НЕ безопасно использовать в рабочем потоке.

Если вы хотите позвонить TVCLReport.Execute() в рабочий поток, но отобразить его предварительный просмотр в потокобезопасном режиме, одним из возможных решений было бы изменить исходный код для TVCLReport, чтобы показать функциональность предварительного просмотра таким образом, чтобы вы могли вызвать его с помощью TThread.Synchronize(), например:

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; 

Хотя, если отчет действительно занимает много времени для создания, то есть вероятность, что просмотр будет также принимать долгое время генерировать. Если это так, это решение не принесет вам ничего полезного. Возможно, было бы проще просто оставить TVCLReport в главном потоке пользовательского интерфейса и отобразить сообщение пользователю, когда он занят созданием отчета.

Вам просто нужно попробовать и посмотреть, что произойдет.

+0

Благодарим вас за ваши усилия и идеи. Я ценю это. Я дам ему попытку и дам вам знать, работает ли это. – ErenRavenHeart

+0

Я не могу понять это ... «dm.rmvFarm.DisplayPreview», «dm.rmvFarm.OnPreview» не объявлены. – ErenRavenHeart

+0

@ErenRavenHeart У вас может быть другая версия Reportmanager, кроме Remy. Или вы не включили правильные исходные файлы в предложение Uses. Используйте документацию. –

 Смежные вопросы

  • Нет связанных вопросов^_^