WPF RichTextBox Document Creation Threading Issue

У меня небольшая проблема с RTB и генерацией документов в отношении потоков.

Когда событие TextChanged запускается в RTB, создается новая тема, и в нее выгружается генерация документа. Это может занять пару секунд с блокирующими вызовами, так что действительно нужно быть в другом потоке, чтобы пользовательский интерфейс оставался отзывчивым.

Проблема I ' m является исключением, когда я пытаюсь добавить вновь созданный документ к свойству Document RTB. ( Вызывающий поток не может получить доступ к этому объекту, потому что он принадлежит другому потоку.) Это происходит не из-за того, что вы забыли использовать Dispatcher.Invoke , поскольку именно здесь генерируется исключение, а потому, что Я создаю экземпляры FlowDocument / Paragraph / Run в потоке, отличном от потока пользовательского интерфейса (я думаю ??).

Есть ли способ достичь того, что я ищу здесь?

Обновление

    private void rtbQuery_TextChanged(object sender, TextChangedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Requires update; on thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);

        backgroundWorker.RunWorkerAsync();
    }

    private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Generating; on thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);

        DocumentGenerator dgen = new DocumentGenerator();
        string queryText = getQueryText();

        e.Result = dgen.GenerateDocument(queryText);
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Assigning; on thread:" + System.Threading.Thread.CurrentThread.ManagedThreadId);

        FlowDocument doc = (FlowDocument)e.Result;
        txtQuery.Document = doc; // ! The calling thread cannot access this object because a different thread owns it
    }

>Requires update; on thread:9
>Generating; on thread:10
>Assigning; on thread:9

Обновление № 2 - Решение

(своего рода)

Итак, как заметил @Jon Mitchell, я не могу обновить свой RTB в потоке пользовательского интерфейса с объектом, созданным в другом потоке. Однако есть очень простое решение, которое требует минимального изменения кода, чтобы обойти это, и я ' м размещать его, чтобы избавить будущих людей от хлопот. Вкратце объясняется, что граф объектов создается в другом потоке, а затем преобразуется в XAML. Затем поток пользовательского интерфейса преобразует этот XAML обратно в граф объектов в своем собственном потоке, и все работает нормально.

    private void backgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        DocumentGenerator dgen = new DocumentGenerator();
        string queryText = getQueryText();

        dgen.GenerateDocument(queryText); // start generation
        e.Result = dgen; // note, i'm passing the generator, not the document
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        DocumentGenerator dgen = (DocumentGenerator)e.Result;
        txtQuery.Document = dgen.GetFlowDocument(); 
    }

В классе DocumentGenerator

    public void GenerateDocument(string data)
    {
        ... // build up the document DOM

        // return documentDOM; // used to return the generated item here.
        documentXAML = System.Windows.Markup.XamlWriter.Save(documentDOM); // serialize the DOM to XAML
    }
    public FlowDocument GetDocument()
    {
        object result = System.Windows.Markup.XamlReader.Parse(documentXAML); // build DOM from XAML
        return (FlowDocument)result;
    }
5
задан jasper 8 April 2011 в 17:00
поделиться