I've created a dependency property to allow a TextBlock to bind to Inlines, which works just fine.
Because my inlines creation is quite heavy I want to do it in a thread separate from the UI thread so that the UI doesn't hang when loading this particular content. However, when I create the inlines in a separate thread, I'm getting an InvalidOperationException
The calling thread cannot access this object because a different thread owns it.
I then made some changes to the dependency property so that I use Dispatcher.Invoke on the object owned by a different thread. However, I then get a TaskCanceledException
A task was canceled.
So, how can I use inlines in a TextBlock when the inlines have been created by a separate thread?
A minimum, complete and verifiable example is a bit big to post in this question (MVVM and all), but this file is a complete Visual Studio solution that will throw the first exception.
Both referenced exceptions happen in the dependency property (TextblockInlineBinding.cs), and this is the PropertyChanged from that file:
private static void OnInlinesPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
var textBlock = obj as TextBlock;
if (textBlock != null)
{
textBlock.Inlines.Clear();
List<Inline> inlines = e.NewValue as List<Inline>;
if (inlines != null) {
// InvalidOperationException is thrown here
textBlock.Inlines.AddRange(inlines);
}
}
}
Changing the Inlines.AddRange() line to use the inline's dispatcher, like this, causes the TaskCancelledException
foreach (Inline inline in inlines) {
// TaskCanceledException is thrown here
inline.Dispatcher.Invoke(() => {
textBlock.Inlines.Add(inline);
});
}