Поскольку программа большая, выделю только те участки кода:
Есть WPF-объект с FlowDocument:
ReportEngine ReportView = new ReportEngine();
VisualSpaceReport.Document = ReportView.ReportData;
Он инициализируется и биндится при запуске программы. Остальное с ним работаю через методы.
Из события PropertyChangedEventArgs вызываю метод
UI.UI_ControlViewer.UI_Viewer.UI_Report.AddLog((sender as Libraries.Events).Value, e.PropertyName);
Сам метод выглядит так:
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();
}//);
Dispatcher.InvokeAsync использую из-за того, что некоторые реализации не используют потоки, что вызывают зависания программы. Пришлось закомментировать, чтобы найти источник проблемы.
ReportView работает нормально, если находиться в основном потоке.
У меня данные приходят (в основном) из потоков. Вся большая часть кода работает нормально.
Но при заходе в Appendf у меня часто возникает сообщение:
"Не удается использовать объект DependencyObject, принадлежащий к другому потоку, отличному от его родительского объекта Freezable."
Проблема возникает именно при форматировании текста. Добавление просто текста работает нормально.
Как мне заставить перевести все эти данные в главный поток или как-то иначе решить проблему с потоками?
P.S. Дополню, как выглядит ReportView.Append и ReportView.Assign, а также общий для них статический метод, где и возникает проблема:
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;
}
И ещё заметил, что для Append и Assign разные типы исключений:
- для Append:
System.InvalidOperationException: "Вызывающий поток не может получить доступ к данному объекту, так как владельцем этого объекта является другой поток."
- для Assign:
System.InvalidOperationException: "Не удается использовать объект DependencyObject, принадлежащий к другому потоку, отличному от его родительского объекта Freezable."
Это происходит при использовании конструкции вызова:
Dispatcher.Invoke(() => { UI.UI_ControlViewer.UI_Viewer.UI_Report.AddLog((sender as Libraries.Events).Value, e.PropertyName); });
В ходе исследования выяснил, что не работают свойства Background, Foreground и TextDecoration. Любая попытка применить новые свойства к ним заканчивается исключением любого из двух типов, что было выше.