'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
- I have implemented a winRT BLE component that wraps the windows bluetooth function
- I am using this component in my winrt application and successfully get a notification when the app connects to me bluetooth device
- 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...
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 |
|---|
