Binding TextBlock inlines created outside UI thread

Viewed 166

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);
    });
}
0 Answers
Related