Создание FlowDocument в потоке BackgroundWorker

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

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

В StackOverflow есть несколько потоков, которые, похоже, связаны с той же проблемой, что и у меня:

В первой ссылке кто-то предлагает следующее:

"Что бы я сделал: использовал XamlWriter и сериализовал FlowDocument в XDocument. Задача сериализации включает в себя Dispatcher, но как только это будет сделано, вы сможете запускать столько дурацких параллельных анализов данных, сколько хотите, и ничего в пользовательский интерфейс повлияет на это. (Кроме того, когда это XDocument, вы запрашиваете его с помощью XPath, который является довольно хорошим молотком, если ваши проблемы на самом деле являются гвоздями.)"

Кто-нибудь может пояснить, что автор имеет в виду?


person JamesPD    schedule 25.04.2012    source источник
comment
Затем окончательный FlowDocument используется для создания XpsDocument, который затем отображается как FixedDocumentSequence с помощью элемента управления DocumentViewer в XAML.   -  person JamesPD    schedule 25.04.2012
comment
Вы создаете документ потока в потоке пользовательского интерфейса, прежде чем начать генерировать контент в фоновом потоке? или что-то подобное?   -  person TheZenker    schedule 25.04.2012


Ответы (2)


Для всех будущих посетителей я столкнулся с той же проблемой и решил все благодаря этой статье статья

В итоге мы создали объект в фоновом потоке.

            Thread loadingThread = new Thread(() =>
        {
            //Load the data
            var documant = LoadReport(ReportTypes.LoadOffer, model, pageWidth);

            MemoryStream stream = new MemoryStream();
            //Write the object in the memory stream
            XamlWriter.Save(documant, stream);
            //Move to the UI thread
            Dispatcher.BeginInvoke(
               DispatcherPriority.Normal,
               (Action<MemoryStream>)FinishedGenerating,
               stream);
        });

        // set the apartment state  
        loadingThread.SetApartmentState(ApartmentState.STA);

        // make the thread a background thread  
        loadingThread.IsBackground = true;

        // start the thread  
        loadingThread.Start();

А затем записал результат в поток памяти как xaml, чтобы мы могли прочитать его обратно в основном потоке.

void FinishedGenerating(MemoryStream stream)
    {
        //Read the data from the memory steam
        stream.Seek(0, SeekOrigin.Begin);
        FlowDocument result = (FlowDocument)XamlReader.Load(stream);

        FlowDocumentScrollViewer = new FlowDocumentScrollViewer
        {
            Document = result
        };
    //your code...

Хотелось бы, чтобы это сэкономило время другим :)

person Saria Houloubi    schedule 10.04.2019

Хотя на самом деле это не ответ на уточнение того, что имеет в виду автор вашей цитаты, возможно, это может быть решением вашей проблемы: если вы подключите себя к событию Application.Idle, вы можете создать свой FlowDocument один за другим там. Это событие все еще находится в потоке пользовательского интерфейса, поэтому у вас не возникнет проблем, таких как фоновый рабочий процесс. Тем не менее, вы должны быть осторожны, чтобы не делать слишком много работы сразу, иначе вы заблокируете свое приложение. Если возможно разделить процесс генерации на небольшие фрагменты, вы можете обрабатывать эти фрагменты один за другим в этом событии.

person Ryu Kajiya    schedule 25.04.2012