returning Task<string> from async method on Microsoft UWP
Asked Answered
F

1

6

I have been trying to return Task from an async method, it creates a folder on a removable device and saves it for future use in the application. However, I am getting the dreaded WME1039, saying I am not using a valid Windows Runtime Type. I have checked here for valid runtime types: Windows Runtime base data types, and string is a valid type.. I am completely stuck and don't really know where to go from here! Am I missing something fundamental with the async/await pattern? My current code is listed below, excuse its roughness, I am simply padding out the concept at the moment!

Calling code:

await LoadExtDrive();

Method:

public async Task<string> LoadExtDrive()
{
    StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
    // Get the first child folder, which represents the SD card.
    IReadOnlyList<StorageFolder> tmp;
    try
    {
        tmp = await externalDevices.GetFoldersAsync();
    }
    catch (Exception ex)
    {
        throw;
    }
    StorageFolder sdCard = ( tmp).FirstOrDefault();
    if (sdCard != null)
    {
     // An Removable device is present..
     var dbdir = 
     await sdCard.CreateFolderAsync(APP_DB_DIR_NAME, CreationCollisionOption.OpenIfExists);
     var dirToken = 
     Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(dbdir);
     return dirToken;
    }
    else
    {
        // No SD card is present.
        return null;
    }
}

And the build error:

Error   WME1039 Method 'WebSocketService.StartupTask.LoadExtDrive()' has a parameter of 
type 'System.Threading.Tasks.Task<System.String>' 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.WebSocketService

Any help would be greatly appreciated, as I am completely confused what this means, let alone why it won't work!

Fourcycle answered 25/6, 2016 at 17:15 Comment(4)
string is a valid WinRT type, but Task<> is not. You can find an AsAsyncAction method in the System.Runtime.WindowsRuntime assembly that can wrap a .NET Task as an IAsyncAction. More info here.Rosinarosinante
thanks for that, i have wrapped it in: public IAsyncOperation<string> LoadDriveAsync() { Task<string> load = LoadExtDrive(); IAsyncOperation<string> to = load.AsAsyncOperation(); return to; } And also made the above "LoadExtDrive()" a private method, that seems to have solved this, seems kinda clunky though to have a wrapper for another method. I shall keep investigating, thanks for the help!Fourcycle
It is a bit clunky but it's certainly not uncommon when exposing an API/ABI to implement things in a way idiomatic to the language (i.e. using Task<>) then expose something more appropriate to the API (i.e. ` IAsyncOperation`). If you find that your wrapping code is getting unwieldy, you might look at completely separating it out from the implementation and making a wrapper layer of your own.Rosinarosinante
@SeanCline Can you put the first comment, about IAsyncAction (and link) as an answer so i can give you the credit? You got me out of a pickle and seems only fair!Fourcycle
P
1

You can refer to this post: https://marcominerva.wordpress.com/2013/03/21/how-to-expose-async-methods-in-a-windows-runtime-component/

Basically wrap the Task method as private method, and make your public method to return as IAsyncOperation.

Preoccupy answered 10/2, 2021 at 19:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.