'How to implement ThreadPool::RunAsync in Winrt/C++

I am trying to understand how I could implement a concurrent thread for processing data in a Winrt/Cpp application.

As background

  1. I have implemented a winRT BLE component that wraps the windows bluetooth function
  2. I am using this component in my winrt application and successfully get a notification when the app connects to me bluetooth device
  3. Now within the app I would like to "spawn" a process that continually sends a request to the BLE device and process the response.

To achieve #3 I thought one approach could be - within the connection notification I would invoke a function called StartDataAcq that uses the threadpool to schedule work, to test out this approach I decided to just use the example shown here

https://docs.microsoft.com/en-us/windows/uwp/threading-async/submit-a-work-item-to-the-thread-pool

to see if it could work

So the implementation looks like this within my code

void Datamanager::BleFound(
        winrt::Windows::Foundation::IInspectable  const& /* sender */,
        uint32_t foundFlags)
    {

        OutputDebugStringW((L"Member function Called from DataManager->" + hstring(std::to_wstring(foundFlags)) + L"\r\n").c_str());

        if (!acqStarted)
        {
            
            StartDataAcq();
            acqStarted = true;
            
        }
    }


    void DataManager::StartDataAcq()
    {
        // The nth prime number to find.
        const unsigned int n{ 99999999 };

        unsigned long nthPrime{ 0 };
        //submit work to thread poool
        m_workItem = Windows::System::Threading::ThreadPool::RunAsync([&](Windows::Foundation::IAsyncAction const& workItem)
            {
                unsigned int progress = 0; // For progress reporting.
                unsigned int primes = 0;   // Number of primes found so far.
                unsigned long int i = 2;   // Number iterator.

                if ((n >= 0) && (n <= 2))
                {
                    nthPrime = n;
                    return;
                }

                while (primes < (n - 1))
                {
                    if (workItem.Status() == Windows::Foundation::AsyncStatus::Canceled)
                    {
                        break;
                    }

                    // Go to the next number.
                    i++;

                    // Check for prime.
                    bool prime = true;
                    for (unsigned int j = 2; j < i; ++j)
                    {
                        if ((i % j) == 0)
                        {
                            prime = false;
                            break;
                        }
                    };

                    if (prime)
                    {
                        // Found another prime number.
                        primes++;

                        // Report progress at every 10 percent.
                        unsigned int temp = progress;
                        progress = static_cast<unsigned int>(10.f * primes / n);

                        if (progress != temp)
                        {
                            std::wstringstream updateString;
                            updateString << L"Progress to " << n << L"th prime: " << (10 * progress) << std::endl;

                            OutputDebugStringW((L"" + updateString.str() + L"\r\n").c_str());
                            // Update the UI thread with the CoreDispatcher.
                            /*
                            Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync(
                                Windows::UI::Core::CoreDispatcherPriority::High,
                                Windows::UI::Core::DispatchedHandler([&]()
                                    {
                                        UpdateUI(updateString.str());
                                    }));
                                    */
                        }
                    }
                }
                // Return the nth prime number.
                nthPrime = i;
            } , Windows::System::Threading::WorkItemPriority::Normal, Windows::System::Threading::WorkItemOptions::TimeSliced);

        

    }

I see the message for the connect notification,

This debug string - OutputDebugStringW((L"Member function Called from DataManager->" + hstring(std::to_wstring(foundFlags)) + L"\r\n").c_str());

however I never see any output from the async workitem.

Can someone please help me spot the issue?

Also are there any better ways to do this? I was reading about co-routines but seeing how the work is data processing locally I do not think a co routine would work

I also was trying to find out how I could spawn a separate thread and manage it within my code - but am not sure how to do it within the winrt/c++ framework

based on Raymond Chen's comment I converted the variables on the stack to std::shared_ptr and the sample works now...

Also stumbled upon this link that explains this better than I can...

https://docs.microsoft.com/en-us/cpp/parallel/concrt/task-parallelism-concurrency-runtime?view=msvc-170#lambdas

void DataManager::StartDataAcq()
    {
        
        
        

        auto n = make_shared<UINT32>(9999);
        auto nthPrime = make_shared<UINT32>(0);

        m_workItem = Windows::System::Threading::ThreadPool::RunAsync([n,nthPrime](Windows::Foundation::IAsyncAction const& workItem)
            {
                unsigned int progress = 0; // For progress reporting.
                unsigned int primes = 0;   // Number of primes found so far.
                int i = 2;   // Number iterator.

                
                if ((*n >= 0) && (*n <= 2))
                {
                    *nthPrime = *n;
                    //return;
                }

                while (primes < (*n - 1))
                {
                    if (workItem.Status() == Windows::Foundation::AsyncStatus::Canceled)
                    {
                        break;
                    }

                    // Go to the next number.
                    i++;

                    // Check for prime.
                    bool prime = true;
                    for (unsigned int j = 2; j < i; ++j)
                    {
                        if ((i % j) == 0)
                        {
                            prime = false;
                            break;
                        }
                    };

                    if (prime)
                    {
                        // Found another prime number.
                        primes++;

                        // Report progress at every 10 percent.
                        unsigned int temp = progress;
                        progress = static_cast<unsigned int>(10.f * primes / *n);

                        if (progress != temp)
                        {
                            std::wstringstream updateString;
                            updateString << L"Progress to " << *n << L" " << i << L" th prime: " << (10 * progress) << std::endl;

                            OutputDebugStringW((L"" + updateString.str() + L"\r\n").c_str());
                            // Update the UI thread with the CoreDispatcher.
                            /*
                            Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync(
                                Windows::UI::Core::CoreDispatcherPriority::High,
                                Windows::UI::Core::DispatchedHandler([&]()
                                    {
                                        UpdateUI(updateString.str());
                                    }));
                                    */
                        }
                    }
                }
                // Return the nth prime number.
                *nthPrime = i;
                std::wstringstream updateString;
                updateString << L"Found the nth prime " << i  << std::endl;

                OutputDebugStringW((L"" + updateString.str() ).c_str());


            } , Windows::System::Threading::WorkItemPriority::Normal, Windows::System::Threading::WorkItemOptions::TimeSliced);

        

    }


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source