Render отчёта в отдельном потоке

Обсуждение Stimulsoft Reports.NET
Аватара пользователя
t0pdevice
Сообщения: 100
Зарегистрирован: 15 авг 2016, 09:59

Render отчёта в отдельном потоке

Сообщение t0pdevice »

Отчёты рендерятся через BackgroundWorker без отображения процесса report.Render(false). Используется собственная реализация для отображения процесса формирования отчёта, с таймером и т.д. Все хорошо, отчёты строятся в отдельном потоке и не блокируют работу в приложении.
Но если в отчёте есть страница StiForm, где необходимо выбрать параметры для построения отчёта. После того, как появляется форма и выбираются все параметры, нажимается кнопка "Построить", приложение блокируется, пока отчёт не построится.
Когда есть форма StiForm также в DoWork используется BeginInvoke для report.Render, иначе будет ошибка "Недопустимая операция в нескольких потоках: попытка доступа к элементу управления не из того потока, в котором он был создан." Это только при условии наличия формы в отчете.

Как можно это исправить?
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Re: Render отчёта в отдельном потоке

Сообщение Леонид »

День добрый!

Внесу свои два цента.

Мы в своё время просто сделали форму отчёта, где есть BackgroundWorker, со всеми методами, которые вы назвали,
а также форма, на которой есть необходимые компоненты (в нашем случае DevExpress), - эта форма и есть необходимые параметры для отчёта.
В сам отчёт мы их не передаём, они попадают в OracleDataAdapter, где прописана stored procedure с binding-переменными, - вот эта процедура и крутится в DoWork().
После выполнения этой процедуры, сразу же (в DoWork()) выполняется .Render(false) и никаких проблем.
Более того, мы тоже используем StiForm, и там иногда рисуем компоненты, но простые, типа введите номер сертификата, количество коробов или что-то, что вводят на складе, т.е. данные, которых нет в базе.
Проблем нет и при этом, даже без BeginInvoke(). Но если используем форму StiForm, то если пользователь уйдёт с формы (OnLeaveForm), то она куда-то пропадает (видимо в Z-дереве) визуально и всё, приходится закрывать отчёт. Никаких Exception и каких-то ошибок мы не наблюдали.
Приложение большое, серьёзное, MDI-интерфейс, каждая форма в своём треде (thread).
Аватара пользователя
t0pdevice
Сообщения: 100
Зарегистрирован: 15 авг 2016, 09:59

Re: Render отчёта в отдельном потоке

Сообщение t0pdevice »

У нас тоже большое MDI-приложение с использованием MEF. Для отображения отчётов также используется отдельная форма. У нас есть разного типа отчёты, где-то мы используем StiForm, а где возможностей не хватает, собственные формы с большими входными параметрами и списками.
Вроде пока тестирую решение, со StiForm все хорошо сейчас.

Вопрос, а есть ли события, когда StiForm появляется или закрывается?
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Re: Render отчёта в отдельном потоке

Сообщение Леонид »

У нас примерно так же. Отчёты тоже разного типа, наследуем от разного типа форм.
Функционала, разумеется недостаточно было изначально, т.к. очень сложные "хотелки" пользователей, поэтому только собственные кастомные формы.

Код: Выделить всё

Вопрос, а есть ли события, когда StiForm появляется или закрывается?
Есть такое. Там два события: LoadForm и ClosedForm в самой StiForm.

Мы иногда в коде использовали не в отчёте, а прямо из кода наших форм примерно так:

Код: Выделить всё

        stiReport = new StiReport();
        stiReport.Load(reportBody);

// далее так
StiForm form = stiReport.Pages["custom_form_name"]; или StiForm form = stiReport.Pages[0]; // по индексу

// или так (в общем, вы поняли)
foreach (StiPage page in stiReport.Pages)
{
        reportInnerForm = (page as StiForm); // save form reference

// events
            reportInnerForm.ClosedForm += new EventHandler(reportInnerForm_ClosedForm);
            reportInnerForm.LoadForm += new EventHandler(ReportInnerForm_LoadForm);
}
Аватара пользователя
t0pdevice
Сообщения: 100
Зарегистрирован: 15 авг 2016, 09:59

Re: Render отчёта в отдельном потоке

Сообщение t0pdevice »

Спасибо, вышло, как хотел.
Использовал:

Код: Выделить всё

report.Pages.OfType<StiForm>().FirstOrDefault()
HighAley
Сообщения: 1998
Зарегистрирован: 08 июн 2011, 11:36
Откуда: Stimulsoft Office

Re: Render отчёта в отдельном потоке

Сообщение HighAley »

Здравствуйте.

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

Спасибо.
Аватара пользователя
t0pdevice
Сообщения: 100
Зарегистрирован: 15 авг 2016, 09:59

Re: Render отчёта в отдельном потоке

Сообщение t0pdevice »

Иногда возникает ошибка:

Код: Выделить всё

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext()
at Stimulsoft.Report.Engine.StiPostProcessProviderV2.PostProcessPages(StiPagesCollection pages)
at Stimulsoft.Report.Engine.StiRenderProviderV2.Render(StiReport report, StiRenderState state)
at Stimulsoft.Report.Engine.StiReportV2Builder.RenderSingleReport(StiReport masterReport, StiRenderState renderState)
at Stimulsoft.Report.StiReport.RenderReport(StiRenderState renderState)
at Stimulsoft.Report.StiReport.Render(StiRenderState renderState, StiGuiMode guiMode)
at Stimulsoft.Report.StiReport.Render(StiRenderState renderState)
at Stimulsoft.Report.StiReport.Render(Boolean showProgress)
Леонид
Сообщения: 329
Зарегистрирован: 23 июл 2009, 09:53
Откуда: Moscow

Re: Render отчёта в отдельном потоке

Сообщение Леонид »

У нас на практике только OutOfMemory на больших отчётах возникает, но таких ошибок не было.
Вы уверены, что в отчёте, который вы рендерите у вас нигде не меняется какая-либо коллекция, типа List<> и пр.?
Аватара пользователя
t0pdevice
Сообщения: 100
Зарегистрирован: 15 авг 2016, 09:59

Re: Render отчёта в отдельном потоке

Сообщение t0pdevice »

Ничего нигде не меняется.
Ivan
Сообщения: 641
Зарегистрирован: 10 авг 2006, 05:40
Откуда: Stimulsoft Office

Re: Render отчёта в отдельном потоке

Сообщение Ivan »

Здравствуйте.

Ошибка возникает в методе StiPostProcessProviderV2.PostProcessPages(StiPagesCollection pages).
Из циклов в этом методе только перебор страниц отчета foreach (StiPage page in pages), т.е. похоже что изменяется коллекция страниц.
Вы уверены, что больше ничего не меняет отчет?
Включен ли в отчёте режим кэширования?

Спасибо.
Ответить