"Element not found" when trying to execute a code every time a timer ticks

0

I'm trying to check if the user's device has entered tablet mode every 1 second using a timer belonging to System.Threading.

The problem is that I get this exception: "System.Exception: 'Element not found. (Exception from HRESULT: 0x80070490)'" when I run this code:

    public MainPage()
    {
        this.InitializeComponent();

        TimerCallback tmCallback = CheckEffectExpiry;
        Timer timer = new Timer(tmCallback, "test", 1000, 1000);
}
        public  void CheckEffectExpiry(object objectInfo)
        {           
                switch (UIViewSettings.GetForCurrentView().UserInteractionMode)
                {
                    case UserInteractionMode.Mouse:
                        debugBox.Text = "mouse";
                        break;

                    case UserInteractionMode.Touch:
                default:
                    debugBox.Text = "tablet";
                    break;
            }
    }

The line that throws the exception is switch(UIViewSettings.GetForCurrentView().UserInteractionMode)

Instead, if I run the code like this (without the timer), the exception does not show up:

public MainPage()
{
switch (UIViewSettings.GetForCurrentView().UserInteractionMode)
                    {
                        case UserInteractionMode.Mouse:
                            debugBox.Text = "mouse";
                            break;

                        case UserInteractionMode.Touch:
                    default:
                        debugBox.Text = "tablet";
                        break;
}
c#
exception
timer
uwp
asked on Stack Overflow Aug 10, 2017 by Samuele Dassatti • edited Aug 10, 2017 by Samuele Dassatti

1 Answer

2

What is happening is that because GetForCurrentView is being called from the timer thread can't resolve the view and retrieve it's settings, then the property tries to read the data and fails as there are no settings. If using a Threading timer you need to use the Dispatcher to invoke the functions on the UI thread. But the better solution is to directly use a DispatcherTimer as it already runs on the UI Thread.

var dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += CheckEffectExpiry;
dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
dispatcherTimer.Start();
//...

void CheckEffectExpiry(object sender, object e)
{
    switch (UIViewSettings.GetForCurrentView().UserInteractionMode)
    {
        case UserInteractionMode.Mouse:
            debugBox.Text = "mouse";
            break;

        default:
            debugBox.Text = "tablet";
            break;
    }
}
answered on Stack Overflow Aug 10, 2017 by Gusman • edited Aug 10, 2017 by Gusman

User contributions licensed under CC BY-SA 3.0