Search code examples
windows-store-appswinrt-async

How to pass execution to the UI thread in a task when having to wait for the result (without Dispatcher) in a Windows Store App?


This is a duplication of my question in the Windows Store Apps Forum:

I have an awaitable method returning a Task. It gets passed a delegate designated to make a decision. The task iterates though some objects and invokes the delegate to determine if an object should be processed. In classic .NET I would implement that as follows:

private Task ProcessDemo(Func<int, bool> processDecisionHandler)
{
   // Get the current SynchronizationContext
   SynchronizationContext synchronizationContext = SynchronizationContext.Current;

   return Task.Run(() =>
   {
      for (int i = 0; i < 10; i++)
      {
         // Invoke the process decision handler in the UI thread 
         bool process = false;
         synchronizationContext.Send((state) => { process = processDecisionHandler(i); }, i);
         if (process)
         {
            // Process the item
            ...
         }
      }
   });
}

This method could be invoked like this:

private async void testButton_Click(object sender, RoutedEventArgs e)
{
   this.WriteLine("UI-Thread ({0})", Thread.CurrentThread.ManagedThreadId);

   Func<int, bool> handler = (i) =>
   {
      if (MessageBox.Show("Process " + i + "?", this.Title, MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.Yes)
      {
         return true;
      }
      else
      {
         return false;
      }
   };

   await this.ProcessDemo(handler);
}

In Windows Store Apps I face the problem that the Send method of SynchronizationContext is not available. Post would obviously not work for my goal since I have to "await" the handler result.

How could I achieve my goal anyway without a Dispatcher (that I do not have in library code)?


Solution

  • If it's always invoked from the UI thread, then you can do something like this:

    private Task ProcessDemo(Func<int, bool> processDecisionHandler)
    {
      for (int i = 0; i < 10; i++)
      {
        // Invoke the process decision handler in the UI thread
        if (processDecisionHandler(i))
        {
          // Process the item on a threadpool thread.
          await Task.Run(...);
        }
      }
    }