Проблема при формировании отчета в фоновом потоке

Обсуждение Stimulsoft Reports.Net
Ответить
Edvard
Сообщения: 38
Зарегистрирован: 02 дек 2008, 18:34

Проблема при формировании отчета в фоновом потоке

Сообщение Edvard » 04 апр 2016, 10:56

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

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

.....
 Task<Stimulsoft.Report.StiReport> ts1 = 
                Task<Stimulsoft.Report.StiReport>.Factory.StartNew(() =>
                    cEdgingInventory.GetMatInvReportByAckAndExpDates(dtAck,dtExp,  facID, facName, this));           
             do //ждать выполнения задачи
             {
                 Application.DoEvents();
                 ts1.Wait(5);
             } while (!ts1.IsCompleted);
            
            stiPreview.Report = ts1.Result;   
Это метод, где формируется отчет.Отчет самостоятельно получает данные из базы, поэтому процесс довольно продолжительный.

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

      public static Stimulsoft.Report.StiReport GetMatInvReportByAckAndExpDates(DateTime adtAck, DateTime adtExplosion, 
                                                                        int aFactoryId, string aFactoryName, ucEdgingInventory cntrl)
        {
           StiReport rpt = new Stimulsoft.Report.StiReport(); 
          .......
          .......    
                rpt.Render(true); //здесь ошибка Cross-thread operation not valid: Control 'frmMain' accessed from a thread other than the thread it was created on.
                                
            return rpt;
        }
На главной форме на время формирования отчета выводится прогрессбар. Собственно ради прогрессбара и для того чтобы сохранить откликаемость главной формы вся эта многопоточность и затевалась.
Но в момент рендеринга возникает ошибка "Cross-thread operation not valid: Control 'frmMain' accessed from a thread other than the thread it was created on." И это совершенно непонятно, т.к. отчет рендерится в том же потоке, где и был создан.
Ошибку удается одолеть двумя способами, первый ч\з invoke и делегат

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

delegate void delRender(bool bl);
...
//потокобезопасный вызов rpt.Render
            if (cntrl.InvokeRequired)
                cntrl.Invoke(new delRender(rpt.Render), new object[] { true });
            else
                rpt.Render(true);                                             
            return rpt;
и второй вызывать rpt.Render(true); уже после получения rpt из фонового потока

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

Task<Stimulsoft.Report.StiReport> ts1 = 
                Task<Stimulsoft.Report.StiReport>.Factory.StartNew(() =>
                    cEdgingInventory.GetMatInvReportByAckAndExpDates(dtAck,dtExp,  facID, facName, this));    
   .............
 stiPreview.Report = ts1.Result;  
 stiPreview.Report.Render(true);
Но оба варианта не совсем то, чего бы хотелось.
Не могли бы вы пояснить причину ошибки и как правильно решать задачу формирования отчета в фоновом потоке?
Использую Stimulsoft 2013.1.16, VS2012, Win7-64
Anton Lozovskiy
Сообщения: 264
Зарегистрирован: 12 ноя 2007, 05:16

Re: Проблема при формировании отчета в фоновом потоке

Сообщение Anton Lozovskiy » 04 апр 2016, 12:58

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

Оба варианта некорректны.
Вы ставите флаг, чтобы показывалось окно прогресса во время рендеринга и этот метод помещаете в
Task<Stimulsoft.Report.StiReport>.Factory.StartNew(() => ......)
Получает там создается и показывается новая форма, к контролам которой идет обращения и изменения свойств (конкретно ProgressBar свойство Value и другие) - этого делать нельзя.

Для вашего случая проще сделать так - создаете свою форму с прогрессом и которую открываете до запуска метода Render, затем асинхронно запускаете метод Render с параметром false и будет у вас красивый прогресс, который не будет зависать.

Спасибо.
Edvard
Сообщения: 38
Зарегистрирован: 02 дек 2008, 18:34

Re: Проблема при формировании отчета в фоновом потоке

Сообщение Edvard » 04 апр 2016, 20:48

Task<Stimulsoft.Report.StiReport>.Factory.StartNew(() => ......)
Получает там создается и показывается новая форма, к контролам которой идет обращения и изменения свойств (конкретно ProgressBar свойство Value и другие) - этого делать нельзя.
Так обращение к свойствам контрола происходит именно из того потока, где эти контролы создавались. Это же корректно.Или нет?
создаете свою форму с прогрессом
Ну нравится мне именно ваше окошко прогресса. В моей форме не будет текстовых сообщений о ходе рендеринга типа "соединение с данными ..." и т.п. Никак нельзя оставить родное окно прогресса?
Aleksey
Сообщения: 2033
Зарегистрирован: 22 апр 2010, 02:57

Re: Проблема при формировании отчета в фоновом потоке

Сообщение Aleksey » 05 апр 2016, 07:13

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

К сожалению, по другому не получится.

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