Maximus
Maximus

Reputation: 1299

How to call RequestAccessAsync() in a Windows Runtime Component (UWP)

I'm trying to create a Background Task in my UWP project, I've followed the documentation from MSDN, but I'm not understanding how I can await the RequestAccessAsync() Task from within the RegisterBackgroundTask function. This is my BackgroundTask class in m y Windows Runtime Component project:

public sealed class BackgroundTask : IBackgroundTask
{
    // Note: defined at class scope so we can mark it complete inside the OnCancel() callback if we choose to support cancellation
    private BackgroundTaskDeferral _deferral;
    private BackgroundTaskCancellationReason _cancelReason = BackgroundTaskCancellationReason.Abort;
    private volatile bool _cancelRequested = false;

    public void Run(IBackgroundTaskInstance taskInstance)
    {
        taskInstance.Task.Completed += TaskInstance_OnCompleted;
        taskInstance.Canceled += TaskInstance_OnCanceled;

        _deferral = taskInstance.GetDeferral();

        //
        // TODO: Insert code to start one or more asynchronous methods using the
        //       await keyword, for example:
        //
        // await ExampleMethodAsync();
        //

        _deferral.Complete();
    }

    //
    // Register a background task with the specified taskEntryPoint, name, trigger,
    // and condition (optional).
    //
    // taskEntryPoint: Task entry point for the background task.
    // taskName: A name for the background task.
    // trigger: The trigger for the background task.
    // condition: Optional parameter. A conditional event that must be true for the task to fire.
    //
    public static async Task<BackgroundTaskRegistration> RegisterBackgroundTask(
        string taskEntryPoint,
        string taskName,
        IBackgroundTrigger trigger,
        IBackgroundCondition condition)
    {
        //
        // Check for existing registrations of this background task.
        //
        foreach (var cur in BackgroundTaskRegistration.AllTasks)
        {

            if (cur.Value.Name == taskName)
            {
                //
                // The task is already registered.
                //
                return (BackgroundTaskRegistration)(cur.Value);
            }
        }

        //
        // Register the background task.
        //
        var builder = new BackgroundTaskBuilder
        {
            Name = taskName,
            TaskEntryPoint = taskEntryPoint
        };

        builder.SetTrigger(trigger);

        if (condition != null)
        {
            builder.AddCondition(condition);
        }

        var access = await BackgroundExecutionManager.RequestAccessAsync();

        if (access != BackgroundAccessStatus.AlwaysAllowed && access != BackgroundAccessStatus.AllowedSubjectToSystemPolicy)
        {
            return default(BackgroundTaskRegistration);
        }

        var task = builder.Register();

        //
        // Associate a completed handler with the task registration.
        //
        task.Completed += new BackgroundTaskCompletedEventHandler(Registered_OnCompleted);

        return task;
    }

    private static void Registered_OnCompleted(IBackgroundTaskRegistration task, BackgroundTaskCompletedEventArgs args)
    {
        var settings = Windows.Storage.ApplicationData.Current.LocalSettings;
        var key = task.TaskId.ToString();
        var message = settings.Values[key].ToString();
        //UpdateUI(message);
    }

    private void TaskInstance_OnCompleted(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
    {
    }

    private void TaskInstance_OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
    {
        //
        // Indicate that the background task is canceled.
        //
        _cancelRequested = true;
        _cancelReason = reason;

        Debug.WriteLine("Background " + sender.Task.Name + " Cancel Requested...");
    }
}

I always get the following compilation error:

error WME1039: Method 'DigitalArtisan.Background.BackgroundTask.RegisterBackgroundTask(System.String, System.String, Windows.ApplicationModel.Background.IBackgroundTrigger, Windows.ApplicationModel.Background.IBackgroundCondition)' has a parameter of type 'System.Threading.Tasks.Task' in its signature. Although this generic type is not a valid Windows Runtime type, the type or its generic parameters implement interfaces that are valid Windows Runtime types. Consider changing the type 'Task' in the method signature to one of the following types instead: Windows.Foundation.IAsyncAction, Windows.Foundation.IAsyncOperation, or one of the other Windows Runtime async interfaces. The standard .NET awaiter pattern also applies when consuming Windows Runtime async interfaces. Please see System.Runtime.InteropServices.WindowsRuntime.AsyncInfo for more information about converting managed task objects to Windows Runtime async interfaces.

Upvotes: 0

Views: 1279

Answers (1)

mm8
mm8

Reputation: 169250

Task<T> is not a WinRT type. IAsyncOperation<T> is:

public static async IAsyncOperation<BackgroundTaskRegistration> RegisterBackgroundTask(
    string taskEntryPoint,
    string taskName,
    IBackgroundTrigger trigger,
    IBackgroundCondition condition)

...

All public methods of a Windows Runtime Component must return WinRT types. Please refer to the following blog post for more information about this and how you could wrap your tasks: http://dotnetbyexample.blogspot.se/2014/11/returning-task-from-windows-runtime.html

//the public method returns an IAsyncOperation<T> that wraps the private method that returns a .NET Task<T>:
public static async IAsyncOperation<BackgroundTaskRegistration> RegisterBackgroundTask(
string taskEntryPoint,
string taskName,
IBackgroundTrigger trigger,
IBackgroundCondition condition)
{
    return RegisterBackgroundTask(taskEntryPoint, taskName, trigger, condition).AsAsyncOperation();
}

//change your current method to be private:
private static async Task<BackgroundTaskRegistration> RegisterBackgroundTask(
    string taskEntryPoint,
    string taskName,
    IBackgroundTrigger trigger,
    IBackgroundCondition condition)
{
    //...
}

The following documenation on MSDN should be helpful as well: https://learn.microsoft.com/en-us/windows/uwp/winrt-components/creating-windows-runtime-components-in-csharp-and-visual-basic

Upvotes: 2

Related Questions