From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

Window with WPF Graph freezes when windows account locked

Hello,

 

I'm experiencing some strange behaviour that I believe to be related to a Graph control in my window. As described, the window containing the graph becomes unresponsive after the windows account is locked (winkey+L) and unlocked. To reproduce this while excluding details specific to my application, I created a stripped down version of my custom control called TestControl with the a graph and a progress bar to indicate whether the UI is responding. Nothing special in the code-behind for this control:

 

<UserControl x:Class="LockBug.Controls.TestControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:ni="http://schemas.ni.com/controls/2009/xaml/presentation"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <ni:Graph Grid.Row="0" Grid.Column="0"
                  x:Name="_graph" 
                  RenderMode="Raster" 
                  FontFamily="Arial" 
                  Foreground="#FF7E7E7E" 
                  FontSize="12" 
                  PlotAreaBackground="#FFF9F9F9" 
                  BorderBrush="{x:Null}"
                  BorderThickness="0"
                  DefaultInteraction="Zoom"
                  PreferIndexData="False">
            <ni:Graph.Plots>
            </ni:Graph.Plots>
            <ni:Graph.Axes>
                <ni:AxisDouble x:Name="_yAxis" Orientation="Vertical" MinorDivisions="{x:Null}">
                    <ni:AxisDouble.LabelTemplate>
                        <DataTemplate>
                            <Label Margin="5" Content="{Binding}"/>
                        </DataTemplate>
                    </ni:AxisDouble.LabelTemplate>
                    <ni:AxisDouble.MajorDivisions>
                        <ni:RangeLabeledDivisions Mode="Count: 11" TickVisibility="Hidden"/>
                    </ni:AxisDouble.MajorDivisions>
                    <ni:AxisDouble.MajorGridLines>
                        <ni:GridLines Stroke="#FFD8D8D8" StrokeThickness="2"/>
                    </ni:AxisDouble.MajorGridLines>
                </ni:AxisDouble>
                <ni:AxisDouble x:Name="_ySecondaryAxis" Orientation="Vertical" Location="Far" MinorDivisions="{x:Null}" Visibility="Hidden">
                    <ni:AxisDouble.MajorDivisions>
                        <ni:RangeLabeledDivisions Mode="Count: 11" TickVisibility="Hidden"/>
                    </ni:AxisDouble.MajorDivisions>
                </ni:AxisDouble>
                <ni:AxisPrecisionDateTime x:Name="_xAxis" Orientation="Horizontal" Label="Time">
                    <ni:AxisPrecisionDateTime.MajorDivisions>
                        <ni:RangeLabeledDivisions>
                            <ni:RangeLabeledDivisions.LabelPresenter>
                                <ni:GeneralValueFormatter Format="yy-MM-dd HH:mm:ss"/>
                            </ni:RangeLabeledDivisions.LabelPresenter>
                        </ni:RangeLabeledDivisions>
                    </ni:AxisPrecisionDateTime.MajorDivisions>
                </ni:AxisPrecisionDateTime>
            </ni:Graph.Axes>
            <ni:Graph.Children>
                <ni:MultiPlotCursor Name="_mpCursor" Visibility="Hidden" TargetBrush="Red">
                </ni:MultiPlotCursor>
            </ni:Graph.Children>
        </ni:Graph>
        <ProgressBar Grid.Row="1" Height="20" IsIndeterminate="True"/>
    </Grid>
</UserControl>

 

I then have a container window called TestContainerWindow which contains two tabs, each with a TestControl. Again, nothing special in the code-behind:

 

<Window x:Class="LockBug.Windows.TestContainerWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Test.Controls"
        Title="TestContainerWindow" Height="300" Width="300">
    <Grid>
        <TabControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
            <TabItem Header="Historical">
                <Grid Background="#FFE5E5E5">
                    <local:TestControl/>
                </Grid>
            </TabItem>
            <TabItem Header="Real Time">
                <Grid Background="#FFE5E5E5">
                    <local:TestControl/>
                </Grid>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

 

 

Finally, my main window has a TextBlock that I'm using as a button to launch the container window:

 

Xaml:

<Window x:Class="LockBug.View.Windows.TestWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:LockBug.Controls"
        Title="TestWindow" Height="300" Width="300">
    <Grid>
        <TextBlock x:Name="_detailsButton" MouseUp="_openPlotWindow" VerticalAlignment="Center" HorizontalAlignment="Center" Text="Details &gt;" Cursor="Hand"/>
    </Grid>
</Window>

 Code:

    public partial class TestWindow : Window
    {
        private TestContainerWindow m_plotWindow = null;

        public TestWindow()
        {
            InitializeComponent();
        }

        public void _openPlotWindow(object sender, RoutedEventArgs e)
        {
            try
            {
                if (m_plotWindow == null)
                {
                    m_plotWindow = new TestContainerWindow();
                    m_plotWindow.Show();
                }
                m_plotWindow.Focus();
            }
            catch (Exception ex)
            {
                MessageBox.Show(string.Format("Unable to show graph window. Exception information: {0}", ex.Message));
            }
        }
    }

 

All you have to do to reproduce is click on Details, see that the progress bar is moving, lock/unlock your computer, and the UI of the graph window should be frozen. Note that if you set Visibility="Hidden" on the Graph control in TestControl.xaml, the UI responds properly after lock/unlock.

 

Hopefully this is enough information to reproduce this problem. A sample project has also been attached containing all required code.

 

As always, your help is much appreciated.

0 Kudos
Message 1 of 22
(8,977 Views)

I am able to reproduce the issue with the project you attached. Polling the state of the application in the debugger, the WPF dispatcher appears to be caught in an infinite loop processing window messages. We do use the dispatcher in the graph to queue work, but all BeginInvoke calls have completed by the time the test page appears on screen.


I have created a task to investigate why the presence of a graph in a separate window breaks the dispatcher after locking the computer. Unfortunately, I have not been able to come up with a viable workaround.

~ Paul H
0 Kudos
Message 2 of 22
(8,959 Views)

Thanks for your response. Do you know what is triggering the dispatcher to loop after an unlock (whether it's a graph redraw or something)? I'm wondering if there could be an override in place somewhere to catch the case where the computer is being unlocked and prevent this from happening.

0 Kudos
Message 3 of 22
(8,957 Views)

Regarding the workaround, I neglected to mention that the issue is only present when both windows are open. After the main window is closed, the remaining window does function correctly. It may be possible to automate closing and re-creating windows by listening to SessionSwitch for unlock events, but this is obviously not ideal.

~ Paul H
0 Kudos
Message 4 of 22
(8,956 Views)

Do you know what is triggering the dispatcher to loop after an unlock (whether it's a graph redraw or something)? I'm wondering if there could be an override in place somewhere to catch the case where the computer is being unlocked and prevent this from happening.


As far as I can see, there is no graph code that runs after the computer is unlocked. We do refresh e.g. during a Loaded event, but no such events are raised on the control that the graph would respond to, and the call stack never contains graph or application code.

~ Paul H
0 Kudos
Message 5 of 22
(8,950 Views)

Unfortunately that isn't an option since the main window in my application (the one that spaws the graph window) needs to stay open permanently. once that window closes the application exits.

0 Kudos
Message 6 of 22
(8,948 Views)

Hello jsacks,

 

I tried running the code you posted and did not experience the progress bar freezing. I didn't see any information in the table object however, I could be missing something. I would also like to know what version of Measurement Studio you are running and what operating system are you using?

 

Regards,

 

-Travis E

National Instruments
Product Marketer
0 Kudos
Message 7 of 22
(8,947 Views)

Hi Travis,

 

The graph doesn't plot anything, the code I posted was just to illustrate the problem. Did you lock/unlock your computer? I'm on Windows 7 using MStudio 2013.

0 Kudos
Message 8 of 22
(8,943 Views)

Short update: Based on the debug callstack, I tried using Spy++ and found that the window containing the graph is being continuously flooded with WM_PAINT messages after the computer is unlocked. Unfortunately, I cannot tell what is posting the messages, or how to stop them (using a WndProc hook to mark the messages as handled did not help).

~ Paul H
0 Kudos
Message 9 of 22
(8,883 Views)

Thanks for the update, I will stay posted.

0 Kudos
Message 10 of 22
(8,879 Views)