locked
What could I do to execute code on UI thread when the App is resuming from suspending state?

    Question

  • I am developing a Windows store app library and I want to execute code on UI Thread when the application is resuming from suspending state.

    Here is an example of my code:

      /* Set the on resuming handler. */
      Application.Current.Resuming += (s, e) =>
      {
        Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
        () =>
        {
          /* Do something on UI thread. */
        });
      };

    The problem is that the RunAsync hangs before it had times to execute any code on the UI thread. In fact, the application hangs on any call to CoreApplication.MainView.

    So, what could I do to execute code on UI thread when the App is resuming from suspending state?

    Thanks
    • Edited by ubikod Thursday, February 13, 2014 12:30 PM
    Thursday, February 13, 2014 8:33 AM

Answers

  • Thanks for the advise. In fact, I found a solution :

          /* Set the new handler. */
          Application.Current.Resuming += (s, e) =>
          {
            /* Start a task to wait for UI. */
            Task.Factory.StartNew(() =>
            {
              Windows.Foundation.IAsyncAction ThreadPoolWorkItem = Windows.System.Threading.ThreadPool.RunAsync(
              (source) =>
              {
                Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                 () =>
                 {
                   /* Do something on UI thread. */
                 });
              });
            });
          };

    This may not be the perfect solution but it works.

    • Marked as answer by ubikod Friday, February 14, 2014 4:37 PM
    Friday, February 14, 2014 4:36 PM

All replies

  • You have to wait for a UI to be available before you can do something with it.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, February 13, 2014 1:31 PM
    Moderator
  • Thank you for your answer Matt.

    How can I wait for a UI to be available in windows store App? Is there an event to subscribe on or kind of a callback?

    Thursday, February 13, 2014 1:43 PM
  • That's a good question that the documentation talks about but doesn't give a solution for:

    Applications should avoid invoking code that puts a high load on the UI thread in response to Resuming. Doing so gives appearance to the user that the shell is being unresponsive, when in fact it is your application code that is the throttle point. Delegate operations to other threads if possible, or use a staged or virtualized approach for rebuilding views and UI whenever the application is resumed.

    http://msdn.microsoft.com/en-US/library/windows/apps/windows.ui.xaml.application.resuming

    You may be able to check if CoreWindow is not null before doing anything to it...  try this and if it doesn't work, let me know.


    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, February 13, 2014 2:09 PM
    Moderator
  • Nice try, but it seems not working. 

    I tested that:

          Application.Current.Resuming += (s, e) =>
          {
            bool testCoreWindow = (CoreApplication.MainView.CoreWindow == null);
          };

    This leads to hang the application too. In fact, any call to CoreWindow freezes the application.


    • Edited by ubikod Thursday, February 13, 2014 2:47 PM
    Thursday, February 13, 2014 2:46 PM
  • Does the Window.Current.Content have any content yet?
    Thursday, February 13, 2014 5:01 PM
  • Based on what you said I made an ugly code but just for the test :

          /* Set the new handler. */
          Application.Current.Resuming += (s, e) =>
          {
            /* Start a task to wait for UI. */
            Task.Factory.StartNew(() =>
            {
              /* Wait till current window is available. */
              while (Window.Current == null)
              {
              }
              Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
              () =>
              {
                /* Do something on UI thread. */
              });
            });
          };
    Trying to wait for UI this way is not working because Window.Current is always 'null' even if the application is successfully resumed, displayed and usable.

    Thursday, February 13, 2014 5:51 PM
  • Are you setting the Content?

    Thursday, February 13, 2014 6:46 PM
  • The code to populate Window.Current is in App.OnLaunched().  I think you should load it in the same manner, then change the UI to whatever you need it to be.

    Matt Small - Microsoft Escalation Engineer - Forum Moderator
    If my reply answers your question, please mark this post as answered.

    NOTE: If I ask for code, please provide something that I can drop directly into a project and run (including XAML), or an actual application project. I'm trying to help a lot of people, so I don't have time to figure out weird snippets with undefined objects and unknown namespaces.

    Thursday, February 13, 2014 7:23 PM
    Moderator
  • CoreWindow is not always available, you better save Dispatcher class in some variable (store for ex., in OnLaunched event) and use that instead of accessing CoreWindow.
    Thursday, February 13, 2014 9:22 PM
  • Thanks for the advise. In fact, I found a solution :

          /* Set the new handler. */
          Application.Current.Resuming += (s, e) =>
          {
            /* Start a task to wait for UI. */
            Task.Factory.StartNew(() =>
            {
              Windows.Foundation.IAsyncAction ThreadPoolWorkItem = Windows.System.Threading.ThreadPool.RunAsync(
              (source) =>
              {
                Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                 () =>
                 {
                   /* Do something on UI thread. */
                 });
              });
            });
          };

    This may not be the perfect solution but it works.

    • Marked as answer by ubikod Friday, February 14, 2014 4:37 PM
    Friday, February 14, 2014 4:36 PM
  • public App()
            {
                this.InitializeComponent();
    
                Application.Current.Resuming += async (s, e) =>
                {
                    CoreDispatcher dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
                    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
                    {
                        var dialog = new MessageDialog("This is being dispatched on the event Dispatcher for the Window.");
                        await dialog.ShowAsync();
                    });
                };
            }
    
    
            protected override void OnLaunched(LaunchActivatedEventArgs args)
            {
                Window.Current.Content = new Page();
                Window.Current.Activate();
            }

    Worth having a quick look at this.
    Friday, February 14, 2014 5:19 PM