FastReport — показ отчета из отдельного потока

В данной статье посмотрим как можно пользоваться многопоточностью в FastReport. Делается это всё достаточно просто, в документации подробно об этом написано. Достаточно учесть несколько нюансов. Мы же разберем самый простой пример — загрузим из файла отчет, экспортируем его в другой файл и отобразим пользователю — и всё это в отдельном потоке.

Почему из отдельного файла? Тут всё от задачи конечно, зависит, но большинство отчетов типовые и их можно хранить в файлах на диске, это сильно экономит место. Вообще, я бы сказал, это наверное даже норма. Другой вариант — хранить отчет в компоненте frxReport — то есть, по сути в оперативной памяти — тоже рабочий, но тут встает вопрос с памятью, если ей небрежно разбрасываться, то….

То есть как это выглядит на практике? Бросаем на форму компонент frxReport, кликаем по нему 2 раза, собираем свой отчет в открывшемся дизайнере, и далее, если решили загружать из файла сохраняем из дизайнера отчет, и удаляем, например компонент frxReport с формы. Если же решили загружать отчет из этого компонента, то соответственно оставляем.

В данном примере всё очень просто — создается поток, который создает внутри себя экземпляр датамодуля, с «заряженными» кодами загрузки, экспорта и показа файла отчета.

Само обращение к файлу, конечно, лучше защищать чем-то вроде критических секций. Так как если планируется массовое обращение к разделяемому ресурсу, то этим, конечно, надо управлять.

13

14

Начнем!

Создадим VCL приложение с одной кнопкой

15

Кнопку обработаем следующим образом

DataModule

Создадим отдельный DataModule и напишем в нём следующее

Юнит потока

Ну и собственно, сам поток

В принципе, пример простой, но я потратил минут 40 на функцию

Почему-то, когда её включаешь, отчет загружается пустой… Но видимо это я в чем-то ещё не разобрался. Но этой функции и нет в рекомендациях разработчиков по потокобезопасности. Вот как они выглядят.

Многопоточность FastReport может работать независимо в разных потоках, но имеется ряд особенностей: — Нельзя создавать TfrxDBDataSet с одинаковыми именами даже в разных потоках, т.к. для поиска используется «глобальный список» и обращение всегда будет происходить к первому созданному TfrxDBDataSet(использование глобального списка можно отключить, по умолчанию активен); — Если во врем выполнения отчета происходит изменение св-в объектов(для примера Memo1.Left := Memo1.Left + 10 в скрипте), то следует помнить, что при последующим выполнении если св-во TfrxReport.EngineOptions.DestroyForms := False шаблон отчета уже будет модифицирован и его необходимо заново загрузить или использовать TfrxReport.EngineOptions.DestroyForms := True. При восстановления из потока нельзя использовать интерактивные отчеты, т.к. объекты скрипта уничтожаются после восстановления, поэтому в некоторых случаях рациональней использовать TfrxReport.EngineOptions.DestroyForms := False и восстанавливать шаблон самостоятельно при следующем цикле построения. При необходимости глобальный список, по которому осуществляется поиск экземпляров TfrxDBDataSet можно отключить.

В принципе, всё достаточно просто, но нюансы как всегда есть. Желаю Вам успехов в освоении такого замечательного продукта как FastReport. Очень, очень много опций и настроек, тут конечно, надо под каждую индивидуальную задачу работать. Но в целом — приятное ощущение проработанности и качества.