Search code examples
c++uwpc++17c++20c++-winrt

How to create "suitable await_ready function" for UWP C++/WinRT app?


I'm trying to create asynchronous event on user clicking a button in my XAMAL C++/WinRT UWP app. I've created Windows Runtime Component having a static IAsyncOperation function and I'm calling it with co_await which creates IntelliSense error:

this co_await expression requires a suitable "await_ready" function and none was found'.

There are no build errors but exceptions like this are thrown on runtime:

Exception thrown at 0x00007FFC4EE3A839 in NOVATeacher.exe: Microsoft C++ exception: winrt::hresult_no_interface at memory location 0x000000A0332FCC60.

This is how I call the function:

IAsyncAction MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    co_await resume_background();

    auto login = co_await NOVAUtils::CurrentLoginAsync();
    myButton().Content(box_value(login));
}

This is how it's declared:

//NOVAUtils.idl
namespace NOVAShared
{
    [default_interface]
    runtimeclass NOVAUtils
    {
        static Windows.Foundation.IAsyncOperation<String> CurrentLoginAsync();
    }
}

//NOVAUtils.h
namespace winrt::NOVAShared::implementation
{
    struct NOVAUtils : NOVAUtilsT<NOVAUtils>
    {
        NOVAUtils() = delete;

        static winrt::Windows::Foundation::IAsyncOperation<hstring> CurrentLoginAsync();
    };
}

//NOVAUtils.cpp
namespace winrt::NOVAShared::implementation
{
    IAsyncOperation<hstring> NOVAUtils::CurrentLoginAsync()
    {
        co_await resume_background();

        static hstring login = []()
        {
            auto users = User::FindAllAsync().get();

            hstring out;
            for_each(begin(users), end(users), [&](User user)
            {
                    hstring dname = unbox_value<hstring>(user.GetPropertyAsync(KnownUserProperties::DisplayName()));
                    out = out + dname + L", ";
            });

            return out;
        }();

        co_return login;
    }
}

The insides of CurrentLoginAsync() are obviously wrong and will give me all the logins and not the current login but that's just for testing now.


Solution

  • For this line

    hstring dname = unbox_value<hstring>(user.GetPropertyAsync(KnownUserProperties::DisplayName()))
    

    The result of user.GetPropertyAsync(KnownUserProperties::DisplayName()) is IAsyncOperation<IInspectable>, we could not convert it to hstring directly. For your requirement, you could append .get()behind the GetPropertyAsync method just like the following.

    user.GetPropertyAsync(KnownUserProperties::DisplayName()).get().
    

    Exception thrown at 0x00007FFC4EE3A839 in NOVATeacher.exe: Microsoft C++ exception: winrt::hresult_no_interface at memory location 0x000000A0332FCC60.

    The build error "winrt::hresult_no_interface" may be caused by above mis-used ,it can not convert IAsuncOperation<IInspectable> to hstring.