Within each thread, a new window is created, with a RadDocing, RadSplitContainer, RadPaneGroup and a single RadPane. The window is then displayed. When you click on the PaneHeader in any window other than the first thread that is opened, the application immediately throws a threading exception: System.InvalidOperationException: The calling thread cannot access this object because a different thread owns it.
This exception occurs even when we have no code other than starting the threads. Has anyone else had this problem? Is there any way to fix this problem?
Thanks,
Daniel
6 Answers, 1 is accepted


Could you please share your code, on how you created multiple rad docking panes on multiple threads? I am trying to do the same but I cannot find my way around it.
It would be great help if you could.
Thanks

I created a small test application that creates windows in different threads, each with their own rad docking pane in the window.
First I set up a window with a button on it that would execute a command to start a new thread
<
Window
x:Class
=
"DockingTest.MainWindow"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
Title
=
"MainWindow"
Height
=
"60"
Width
=
"100"
>
<
Grid
>
<
telerik:RadButton
Content
=
"Start Thread"
Command
=
"{Binding Path=StartThread}"
/>
</
Grid
>
</
Window>
This is all bound to the MainWindowViewModel which executes the StartThread command.
public
class
MainWindowViewModel
{
public
ICommand StartThread {
get
;
set
; }
public
MainWindowViewModel()
{
StartThread =
new
RelayCommand(StartDockingInNewThread);
}
private
void
startNextThread()
{
System.Windows.Window w =
new
System.Windows.Window() { Height = 300, Width = 300 };
try
{
DockingView pv =
new
DockingView();
w.Content = pv;
w.Show();
Dispatcher.Run();
}
catch
(Exception e)
{
}
finally
{
var dispatcher = w.Dispatcher;
if
(!dispatcher.HasShutdownStarted)
{
dispatcher.InvokeShutdown();
}
}
}
private
void
StartDockingInNewThread()
{
Thread thread =
new
Thread(
new
ParameterizedThreadStart(
new
Action<
object
>((o) =>
{
startNextThread();
})));
thread.SetApartmentState(ApartmentState.STA);
thread.Start(
new
object
());
Thread.Sleep(1);
}
}
The method StartDockingInNewThread() creates the new thread, and starts it.
When startNextThread() executes, it creates the new window, adds the contents of the window, displays it and then invokes Dispatcher.Run() to cause the thread to start listening for events.
The DockingView is a UserControl that contains a rad docking pane
<
UserControl
x:Class
=
"DockingTest.DockingView"
xmlns:telerikDocking
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Docking"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
xmlns:DockingTest
=
"clr-namespace:DockingTest"
mc:Ignorable
=
"d"
>
<
Grid
>
<
telerikDocking:RadDocking
HasDocumentHost
=
"False"
x:Name
=
"_docking"
>
<
telerikDocking:RadSplitContainer
InitialPosition
=
"DockedLeft"
Orientation
=
"Vertical"
x:Name
=
"_splitLeft"
>
<
telerikDocking:RadPaneGroup
x:Name
=
"_group"
telerikDocking:ProportionalStackPanel.RelativeSize
=
"1, 2"
AllowDragReorder
=
"True"
AllowDragOverTab
=
"True"
>
<
telerikDocking:RadPane
x:Name
=
"_pane"
Header
=
"Invintory"
CanUserClose
=
"True"
IsSelected
=
"True"
>
<
TextBlock
Text
=
"This is some Text"
/>
</
telerikDocking:RadPane
>
</
telerikDocking:RadPaneGroup
>
</
telerikDocking:RadSplitContainer
>
</
telerikDocking:RadDocking
>
</
Grid
>
</
UserControl
>
Under normal, non-threading circuimstances this works as expected. However, when opening up multiple threads with RadDocking, only the first thread opened will work as expected. In order to fix this problem, the style used for the PaneHeader needs to be overwritten.
I created a Resource Dictionary to overwrite this style
<
ResourceDictionary
xmlns
=
"http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:telerik
=
"http://schemas.telerik.com/2008/xaml/presentation"
>
<!--PaneHeader Style-->
<
Style
x:Key
=
"PaneHeaderStyle"
TargetType
=
"telerik:PaneHeader"
>
<
Setter
Property
=
"telerik:InputBindingsManager.InputBindings"
>
<
Setter.Value
>
<
InputBindingCollection
>
<
MouseBinding
Command
=
"telerik:RadDockingCommands.PaneHeaderMenuOpen"
>
<
MouseBinding.Gesture
>
<
MouseGesture
MouseAction
=
"RightClick"
/>
</
MouseBinding.Gesture
>
</
MouseBinding
>
</
InputBindingCollection
>
</
Setter.Value
>
</
Setter
>
</
Style
>
<!--Set the style-->
<
Style
TargetType
=
"telerik:PaneHeader"
BasedOn
=
"{StaticResource PaneHeaderStyle}"
/>
</
ResourceDictionary
>
Once you create the Resource Dictionary, then you need to use it in the DockingView by adding it to your UserControl.Resources in the xaml
<
UserControl.Resources
>
<
ResourceDictionary
Source
=
"Dictionary1.xaml"
/>
</
UserControl.Resources
>
After adding this resource dictionary to redefine the input bindings, you can run multple threads without them crashing.
I hope this helps,
Daniel


Thanks in advance.
Danny
You could find a lot of information about how to implement a multi UI thread on net, for example:
- http://eprystupa.wordpress.com/2008/07/28/running-wpf-application-with-multiple-ui-threads/
- http://msdn.microsoft.com/en-us/magazine/cc163328.aspx
- http://msdn.microsoft.com/en-us/library/ms741870.aspx
- http://blogs.msdn.com/b/dwayneneed/archive/2007/04/26/multithreaded-ui-hostvisual.aspx
You could run RadDocking in a separate Window using the follow code:
private
void
Button_Click_1(
object
sender, RoutedEventArgs e)
{
Thread newWindowThread =
new
Thread(
new
ThreadStart(ThreadStartingPoint));
newWindowThread.SetApartmentState(ApartmentState.STA);
newWindowThread.Start();
}
private
void
ThreadStartingPoint()
{
var tempWindow =
new
DockingView();
tempWindow.Show();
System.Windows.Threading.Dispatcher.Run();
}
The RadDocking control is placed into the DockingView which inherits Window. Anyway, please note that the RadDocking is not design to run in different thread and there could be some unexpected problems.
Regards,
George
Telerik
Explore the entire Telerik portfolio by downloading Telerik DevCraft Ultimate.