0

I have a DevExpress RichEditControl which is taking a very long time to load on my page, so rather than lock the UI while it loads in as static XAML, I'm using a new thread to append it to an existing DockPanel:

private bool Working { get; set; }

protected void btnAdd_Click(object sender, RoutedEventArgs e)
{
    var thread = new Thread(new ThreadStart(LoadEditorView));
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
}

private void LoadEditorView()
{
    // Indicate that a this worker thread is busy.
    Working = true;

    // Create a new RichEditControl to be rendered on the Page.
    var rte = new RichEditControl();
    rte.CommandBarStyle = CommandBarStyle.Ribbon;
    rte.DocumentSource = null;
    rte.SetBinding(RichEditControl.DocumentSourceProperty, new Binding("Body"));
    DockPanel.SetDock(rte, Dock.Bottom);

    // Append the RichEditControl to the DockPanel that it should be in.
    dpEditorPanel.Dispatcher.Invoke((() => dpEditorPanel.Children.Add(rte)));
}

When its time to add the editor to the dockpanel's children, I'm getting an InvalidOperationException saying that:

The calling thread cannot access this object because a different thread owns it.

I was to understand that using the Dispatcher was the way to go to avoid this very issue (even if it may not necessarily be the most correct way to do it in the first place).

Have I missed something? How can I fix the problem?

Ortund
  • 8,095
  • 18
  • 71
  • 139
  • @Sinatr not the same, the issue highlighted in that question didn't already implement thread safe property manipulation the way I have. – Ortund Jul 14 '17 at 12:28
  • 1
    All changes that you make to the UI need to be done on the UI thread. You can't speed things up by getting more threads involved. – satnhak Jul 14 '17 at 12:29
  • 1
    The problem is not in your Dispatcher Call but this, `dpEditorPanel` is not accessible from the current thread because it is on the UI thread – Suraj S Jul 14 '17 at 12:29
  • 1
    You have to invoke every UI call, including creation, so wrapping a complete method will do. @Ortunt, I just want the question to be closed as fast as possible, because it's all about invoke. – Sinatr Jul 14 '17 at 12:29
  • 1
    Bad idea since you can only access and use a UI Control on the thread on which it was originally created. So just forget about this approach of creating a control on one thread and then add it to another control on Another thread because it won't work. – mm8 Jul 14 '17 at 12:30
  • @Sinatr what you should want is the OP to solve their problem. not get the question closed. – satnhak Jul 14 '17 at 12:30
  • @briantyler, this was asked so many times. I don't see a point in a other *quick answer* here. – Sinatr Jul 14 '17 at 12:31
  • @mm8 that's remarkably unhelpful. Would you happen to have any alternative approaches that would actually work? – Ortund Jul 14 '17 at 12:31
  • @briantyler I said it was to speed it up, but that's a misnomer actually. The idea is to keep the UI responsive while the thing is loading so that the user doesn't think it broke – Ortund Jul 14 '17 at 12:32
  • @Sinatr, you haven't even referenced the right dupe. I think you should just let this go and see if anyone can help. – satnhak Jul 14 '17 at 12:33
  • *"I'm using a new thread to append it to an existing DockPanel"* - this is an attempted solution. *"RichEditControl which is taking a very long time to load"* - this is the problem. Solve the problem, instead of asking to solve attempted solution (which is wrong). – Sinatr Jul 14 '17 at 12:33
  • @Ortund Why not use `Application.Current.Dispatcher.Invoke()` – Suraj S Jul 14 '17 at 12:35
  • create `RichEditControl rte = null;` on the main thread and then call this on your background thread `rte = new RichEditControl();` then call `dpEditorPanel.Dispatcher.Invoke((() => dpEditorPanel.Children.Add(rte)));` – XAMlMAX Jul 14 '17 at 13:23

0 Answers0