M
M
Mikhail Usotsky2019-02-09 00:16:53
WPF
Mikhail Usotsky, 2019-02-09 00:16:53

How to transfer all data to the main thread for report output?

Since the program is large, I will highlight only those sections of the code:
There is a WPF object with a FlowDocument:

ReportEngine ReportView = new ReportEngine();

VisualSpaceReport.Document = ReportView.ReportData;

It is initialized and bound when the program starts. The rest I work with him through methods.
From the PropertyChangedEventArgs event I call the method
UI.UI_ControlViewer.UI_Viewer.UI_Report.AddLog((sender as Libraries.Events).Value, e.PropertyName);

The method itself looks like this:
public void AddLog(object value, string propertyName)// => Dispatcher.InvokeAsync(() =>
{
    switch (propertyName)
    {
        case "Append":
            ReportView.Append(value as string, new Libraries.Interfaces.Formatting());
            break;
        case "Assign":
            ReportView.Assign(value as string);
            break;
        case "Create table":
            ReportView.Create(value as string);
            break;
        case "Close table":
            ReportView.Close(value as string);
            break;
        case "Table":

            switch (value)
            {
                case Structures.TableForProcessing.Add add_process:
                    ReportView.Add(add_process.id, add_process.text, add_process.value, add_process.formattingText, add_process.formattingValue);
                    break;

                case Structures.TableForProcessing.Assign assign_process:
                    ReportView.Assign(assign_process.id, assign_process.index, assign_process.value, assign_process.processing);
                    break;

                case Structures.TableForReporting.Setting setting_process:
                    ReportView.Setting(setting_process.id, setting_process.index, setting_process.background);
                    break;

                case Structures.TableForReporting.Add add:
                    ReportView.Add(add.id, add.text, add.value);    //?  add.formatting -- не работает (вызывает конфликт потока [Freezable])
                    break;

                case Structures.TableForReporting.Assign assign:
                    ReportView.Assign(assign.id, assign.index, assign.select, assign.value, assign.formatting);
                    break;
            }

            break;
        case "Appendf":

            switch (value)
            {
                case Structures.DataForReporting.Add add:
                    ReportView.Append(add.text, add.formatting); //?  add.formatting -- не работает (вызывает конфликт потока [Freezable])
                        break;
            }

            break;
    }

    VisualSpaceReport.FindScrollViewer()?.PageDown();
}//);

I use Dispatcher.InvokeAsync because some implementations don't use threads, which causes the program to hang. Had to comment out to find the source of the problem.
The ReportView works fine when on the main thread.
My data comes (mostly) from streams. Most of the code works fine.
But when I enter Appendf, I often get a message:
"Cannot use a DependencyObject that belongs to a different thread than its Freezable parent."

The problem arises precisely when formatting the text. Adding just text works fine.
How can I force all this data to be transferred to the main thread, or somehow solve the problem with threads?
PS I'll add how ReportView.Append and ReportView.Assign look like, as well as a common static method for them, where the problem occurs:
public void Append(string text, Interfaces.Formatting formatting = null) //! В отличие от Append в базовых классах он создаёт и добавляет текст. Вариант быстрого создания абзаца с текстом.
{
    if (formatting != null) formatting.Margin = new Thickness(0, 0, 0, 10);
    ReportData.Blocks.Add(Interfaces.Base.Paragraph.Create(formatting));
    Interfaces.Base.Paragraph.Assign(ReportData.Blocks.Last() as Paragraph, text, formatting);
}

public void Assign(string text, Interfaces.Formatting formatting = null)
{
    Interfaces.Base.Paragraph.Assign(ReportData.Blocks.Last() as Paragraph, text, formatting);
}


public static System.Windows.Documents.Paragraph Assign(System.Windows.Documents.Paragraph target, string text, Formatting formatting = null)
{
    ToSpan(target).Inlines.Clear();

    if (formatting != null)
        // здесь форматирование не работает от потоков, только те, которые находятся в главном потоке.
        ToSpan(target).Inlines.Add(new Run(text)
        {
            Background = formatting.Background,
            Foreground = formatting.Foreground,

            FontFamily = formatting.FontFamily,
            FontSize = formatting.FontSize,
            FontStretch = formatting.FontStretch,
            FontStyle = formatting.FontStyle,
            FontWeight = formatting.FontWeight,

            TextDecorations = formatting.TextDecoration
        });
    else
        ToSpan(target).Inlines.Add(text);

    return target;
}

And I also noticed that for Append and Assign different types of exceptions:
  • for append:
    System.InvalidOperationException: "Вызывающий поток не может получить доступ к данному объекту, так как владельцем этого объекта является другой поток."

  • for assignment:
    System.InvalidOperationException: "Не удается использовать объект DependencyObject, принадлежащий к другому потоку, отличному от его родительского объекта Freezable."


This happens when using the call construct:
Dispatcher.Invoke(() => { UI.UI_ControlViewer.UI_Viewer.UI_Report.AddLog((sender as Libraries.Events).Value, e.PropertyName); });

During the research, I found out that the Background, Foreground and TextDecoration properties do not work. Any attempt to apply new properties to them ends up excluding either of the two types above.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
C
CHolfield, 2019-02-09
@CHolfield

Wrap the AddLog call like this

ReportView.invoke((MethodInvoker)delegate
                {
                    AddLog();//параметры не забудь
                });

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question