I get error C2338 when converting the CX/C++ version of Windows-universal-samples-master ExtendedExecution example

David Hoffman 41 Reputation points
2023-05-08T13:59:36.98+00:00

I have become very good at converting CX/C++ code to win/rt, but this one stumps me. It is only one line that I can't seem to get right and I get this error. C2338. The line is the create_task in BeginExtendedExecution(). Two things lead me here. I could not get the OnSuspending() to accept an IAsyncAction instead of a void, so I put the asynchronous action in another function and just passed in the variables I needed since I could not declare them in the .h file like the CX/C++ example does. Those problems were solved, but I cannot figure out what this error means or how to solve it. Any help would be appreciated.

incorrect parameter type for the callable object in 'then'; consider _ExpectedParameterType or task<_ExpectedParameterType>

void App::OnSuspending([[maybe_unused]] IInspectable const& sender, [[maybe_unused]] SuspendingEventArgs const& args)
{
    SuspendingDeferral deferral = args.SuspendingOperation().GetDeferral();
    ExtendedExecutionSession session = ExtendedExecutionSession();
    session.Reason(ExtendedExecutionReason::SavingData);
    session.Description(L"Saving Data");

    event_token revokedToken = session.Revoked(TypedEventHandler<IInspectable, ExtendedExecutionRevokedEventArgs>(this, &App::ExtendedExecutionSessionRevoked));

    BeginExtendedExecution(session, deferral, revokedToken);
}


IAsyncAction App::BeginExtendedExecution(ExtendedExecutionSession session, SuspendingDeferral deferral, event_token revokedToken)
{
    create_task(session.RequestExtensionAsync()).then([this](ExtendedExecutionResult result) //<--- this line has the problem
    {
        // Save the settings that have not be saved when exiting.
        switch (result)
        {
        case ExtendedExecutionResult::Allowed:
            // Save settings that have changed.
			// I will be using a MessageDialog to ask the user if they what to save settings.

            break;
        case ExtendedExecutionResult::Denied:
            // Just save the settings without asking the user.
			
            break;
        default:
            break;
        }
    }).then([this, session, deferral, revokedToken]()
    {
        // Handle closing the session.
        if (session != nullptr)
        {
            // Revoke the handler.
            session.Revoked(revokedToken);

            session.Close();
            session = nullptr;
        }

        // Handles the deferral completion.
        if (deferral != nullptr)
        {
            deferral.Complete();
            deferral = nullptr;
        }
	});
}

Windows 10
Windows 10
A Microsoft operating system that runs on personal computers and tablets.
10,617 questions
Universal Windows Platform (UWP)
{count} votes

Accepted answer
  1. Junjie Zhu - MSFT 14,751 Reputation points Microsoft Vendor
    2023-05-11T09:35:28.7333333+00:00

    Hi @David Hoffman Welcome to Microsoft Q&A

    According to the documentation Asynchrony, and interop between C++/WinRT and C++/CX.

    C++/WinRT prefers the coroutine co_await model of async operation.

    IAsyncAction App::BeginExtendedExecution(ExtendedExecutionSession session, SuspendingDeferral deferral, event_token revokedToken)
    {
        auto lifetime = get_strong(); // ensure "this" lives during the full coroutine
        auto result = co_await session.RequestExtensionAsync();
        if (result == ExtendedExecutionResult::Allowed) {
            // ... 
        }
        else if (result == ExtendedExecutionResult::Denied) {
            // ...
        }
        session.Close();
        deferral.Complete();
    }
    
    

    Thank you

    Junjie


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Limitless Technology 43,931 Reputation points
    2023-05-09T11:15:42.5666667+00:00

    Hi,

    I'd be happy to help you out with your question. Sorry for the inconvenience caused.

    The error C2338 in C++/WinRT indicates a mismatch between the expected parameter type and the actual type provided when using the then method. In your case, the issue lies in the line where you call create_task(session.RequestExtensionAsync()).then(this.

    To resolve this error, you need to modify the lambda function to match the expected parameter type. The then method expects a callable object that takes a parameter of type concurrency::task<T>, where T is the expected return type. In your code, you are providing a lambda function that takes a parameter of type ExtendedExecutionResult, causing the type mismatch.

    To fix this, you should update the lambda function to take a parameter of type concurrency::task<ExtendedExecutionResult>. Here's the updated code:

    IAsyncAction App::BeginExtendedExecution(ExtendedExecutionSession session, SuspendingDeferral deferral, event_token revokedToken) { create_task(session.RequestExtensionAsync()).then(this { ExtendedExecutionResult result = resultTask.get(); // Save the settings that have not been saved when exiting. switch (result) { case ExtendedExecutionResult::Allowed: // Save settings that have changed. // You can use a MessageDialog to ask the user if they want to save settings. break; case ExtendedExecutionResult::Denied: // Just save the settings without asking the user. break; default: break; } }).then(this, session, deferral, revokedToken { // Handle closing the session. if (session != nullptr) { // Revoke the handler. session.Revoked(revokedToken); session.Close(); session = nullptr; } // Handle deferral completion. if (deferral != nullptr) { deferral.Complete(); deferral = nullptr; } }); }

    By making these modifications, you ensure that the lambda function's parameter type matches the expected type, resolving the error.

    Please ensure that you have included the necessary headers for the concurrency namespace and that you have set up the required dependencies correctly in your project.

    If you have any other questions or need assistance with anything, please don't hesitate to let me know. I'm here to help.

    If the reply was helpful, please don’t forget to upvote or accept as answer, thank you.