This is a migrated thread and some comments may be shown as answers.

RadDocking in multiple threads

6 Answers 273 Views
Docking
This is a migrated thread and some comments may be shown as answers.
Daniel
Top achievements
Rank 1
Daniel asked on 18 Jun 2012, 04:53 PM
I'm currently working on a project that has different windows opened up in multiple threads. There seems to be a problem with commands running in all but the first thread that is created with a RadDocking element in it.

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

Sort by
0
Daniel
Top achievements
Rank 1
answered on 18 Jun 2012, 10:03 PM
I eventually fixed this problem by redefining the style for the PaneHeader. The default styles define the input commands to be executed, by redefining this in the xaml where the docking pane is used it fixed the problem.
0
Aracna
Top achievements
Rank 1
answered on 19 Jun 2012, 02:10 AM
Hi Daniel,

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 
0
Daniel
Top achievements
Rank 1
answered on 19 Jun 2012, 05:40 PM

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:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             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

                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    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





0
Aracna
Top achievements
Rank 1
answered on 21 Jun 2012, 07:54 AM
Thanks Daniel
0
Vinay
Top achievements
Rank 1
answered on 31 May 2013, 01:06 PM
I have a similar problem when I click on the Pane Header, and then it will crash when I launch it in multiple dispatcher thread. I used the solution you described, but it still crashes. Is there any other solutions? I have spent a couple of days trying to fix it.

Thanks in advance.

Danny
0
George
Telerik team
answered on 05 Jun 2013, 01:31 PM
Hello Danny,

You could find a lot of information about how to implement a multi UI thread on net, for example:

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.

Tags
Docking
Asked by
Daniel
Top achievements
Rank 1
Answers by
Daniel
Top achievements
Rank 1
Aracna
Top achievements
Rank 1
Vinay
Top achievements
Rank 1
George
Telerik team
Share this question
or