Search code examples
c#.netwpfperformancetouch

Can I lessen the overhead of stylus/touch input in a WPF application?


I’ve come to realise that using a touchscreen (one that generates stylus & touch events and not just mouse events) seems to cause significant overhead on the UI thread in a WPF application. Even a simple application can be brought to a halt if I place enough fingers on the screen, over the application, and move them about a bit on certain machines. It seems quite peculiar and on the face of it, mostly outside of my control. Using a profiler revealed a lot of time spent mainly in StylusLogic/InputManager code (Windows.Input) and the Dispatcher.GetMessage routine.

I haven’t been able to find any “best practices” for this sort of thing and the closest solution I could come to was to disable touch support wholly (MSDN: Disabling the RealTimeStylus) and hook into WM_TOUCH messages myself, generating my own PreviewTouchDown/PreviewMouseDown events (sort of described here under “Another WPF only way”: CodeProject: WPF and multi touch) but this isn’t without its own issues at times and doesn’t strike me as a long-term sensible solution. I also tried flagging events as handled early on to prevent them tunnelling/bubbling; I flagged every PreviewStylusMove event (the most frequent event) as handled at the main window view as an experiment and this didn’t seem to provide a huge gain. While the codeproject link above states that there was (or is) a bug in WPF for multi-touch, I have found that even single-touch on a less powerful PC than my developer setup (with some actual business software I work on) will lag and stall for seconds at a time and you can still observe an unusual amount of work using task manager / a profiler to observe the CPU performance with single-touch.

Can I do anything to reduce the frequency of these events (E.G. PreviewStylusMove)? Do I have other options or is it all out of my control?

Obviously, I can work on trying to improve the efficiency of the application in general, but stylus/touch seems like such a big initial performance hit that it would be good to know what I can do to mitigate that.

Full disclosure: This is a .NET 4.5 application. I have tried this on different models/brands of touchscreen with no visible differences. My computer and application are set up with the expectation that push-and-hold behaviour is identical to holding down a left mouse button, NOT generating a right click event. I have tested this on both Windows 7 and Windows 8.1 machines with no differences.

The example below is a simple application I used to test this. When I place 10 fingers on the application window it stalls momentarily or skip frames on certain computers I've used (others may be too fast to display lag but the load increase can be observed in something like task manager):

<Window x:Class="SimpleApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SimpleApplication"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Rectangle Fill="Aqua" Width="150" Height="150" RenderTransformOrigin="0.5, 0.5">
        <Rectangle.RenderTransform>
            <RotateTransform />
        </Rectangle.RenderTransform>
        <Rectangle.Triggers>
            <EventTrigger RoutedEvent="Loaded">
                <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimation Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)"
                                         To="-360"
                                         Duration="0:0:2"
                                         RepeatBehavior="Forever" />
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Rectangle.Triggers>
    </Rectangle>
</Grid>

Doesn't lag on my machine with an i7-2600 3.4GHz processor, but it does lag on my machine with a Core 2 Duo 2.93GHz processor.


Solution

  • The WPF Team did some touch fixes in 4.6 and 4.6.1. (I'm a software engineer on the WPF Team)

    The engineer who did that work, after reading this question said: * Yeah 4.6.1 should have helped that significantly. * They should also make sure heavy processing is done outside of the touch events themselves since that will tie up the main thread.

    4.6.1 Release candidate was made available in October 2015.

    Thanks, Rob Relyea

    http://twitter.com/rrelyea