0

I'm working in UWP and need to call the UI thread, which I've done by wrapping the call in a Dispatcher.RunAsync(...) call. The code below doesn't compile, because:

Anonymous function converted to a void returning delegate cannot return a value

public async Task<RecentPlaysInfo> GetRecentPlayInfoAsync()
{
  await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
  {

    // This code is on the UI thread: 
    IReadOnlyList<MediaTimeRange> list = meCurrentMedia.MediaPlayer.PlaybackSession.GetPlayedRanges();

    for (int i = 0; i < list.Count; i++)
    {
      // if some criteria on list[i] is met: 
      return new RecentPlaysInfo(...);
    }

  });
}

Brief aside: I tried isolating the Dispatcher.RunAsync(...) call so that it set a variable rather than going return, but the execution seemed to disappear into a blackhole and so I've found myself on this path, at least for now.

This thread helped me de-anonymize it (code below, note the additional return so that all paths return a value) but now the compile error is:

cannot convert from 'System.Func<Regal.Common.RecentPlaysInfo>' to 'Windows.UI.Core.DispatchedHandler'

await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, (Func<RecentPlaysInfo>)(() =>
{

  // This code is on the UI thread: 
  IReadOnlyList<MediaTimeRange> list = meCurrentMedia.MediaPlayer.PlaybackSession.GetPlayedRanges();

  for (int i = 0; i < list.Count; i++)
  {
    // if some criteria on list[i] is met: 
    return new RecentPlaysInfo(...);
  }
                
  return null;
}));

I also read this (kaffekopp's answer) and this (Jon Skeet's answer) but I don't even pretend to fully understand them :(

I was able to code-up and call kaffekopp's modified DispatchToUI(...) method but that simply gives me:

cannot convert from 'System.Func' to 'System.Action'

Adrian K
  • 9,880
  • 3
  • 33
  • 59
  • 1. ***I tried isolating the `Dispatcher.RunAsync(...)` call so that it set a variable rather than going return...*** Such approach must work. Please, share code that you tried with this approach. 2. The second argument of the method `Dispatcher.RunAsync` is declared as a delegate that accepts no arguments and returns `void`, therefore you cannot return a value from it. And the first compiler error in your post says it. – Iliar Turdushev Sep 07 '20 at 06:04

1 Answers1

1

Your GetRecentPlayInfoAsync in returning a Task<RecentPlaysInfo>, so you can do it like below.

public async Task<RecentPlaysInfo> GetRecentPlayInfoAsync()
{
    RecentPlaysInfo info = new RecentPlaysInfo();
    await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {

        // This code is on the UI thread: 
        IReadOnlyList<MediaTimeRange> list = meCurrentMedia.MediaPlayer.PlaybackSession.GetPlayedRanges();

        for (int i = 0; i < list.Count; i++)
        {
            // if some criteria on list[i] is met: 
            info = new RecentPlaysInfo(...);
        }

    });

    return info;
}
Vincent
  • 3,124
  • 3
  • 21
  • 40