Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
ważne interfejsy API
Dowiedz się, jak pracować w osobnym wątku, przesyłając element roboczy do puli wątków. Ta funkcja służy do utrzymania dynamicznego interfejsu użytkownika podczas wykonywania pracy, która zajmuje zauważalny czas i używa jej do równoległego wykonywania wielu zadań.
Tworzenie i przesyłanie elementu roboczego
Utwórz element roboczy, wywołując polecenie RunAsync. Przekaż delegata do wykonania zadania (możesz użyć wyrażenia lambda lub funkcji delegowanej). Zwróć uwagę, że funkcja RunAsync zwraca obiekt IAsyncAction ; zapisz ten obiekt do użycia w następnym kroku.
Dostępne są trzy wersje narzędzia RunAsync , dzięki czemu można opcjonalnie określić priorytet elementu roboczego i określić, czy jest uruchamiany współbieżnie z innymi elementami roboczymi.
Poniższy przykład tworzy element roboczy i przekazuje wyrażenie lambda do wykonania zadania:
// The nth prime number to find.
const uint n = 9999;
// Receives the result.
ulong nthPrime = 0;
// Simulates work by searching for the nth prime number. Uses a
// naive algorithm and counts 2 as the first prime number.
// Capture the DispatcherQueue before entering the background lambda.
var dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
IAsyncAction asyncAction = Windows.System.Threading.ThreadPool.RunAsync(
(workItem) =>
{
uint progress = 0; // For progress reporting.
uint primes = 0; // Number of primes found so far.
ulong i = 2; // Number iterator.
if ((n >= 0) && (n <= 2))
{
nthPrime = n;
return;
}
while (primes < (n - 1))
{
if (workItem.Status == AsyncStatus.Canceled)
{
break;
}
// Go to the next number.
i++;
// Check for prime.
bool prime = true;
for (uint 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.
uint temp = progress;
progress = (uint)(10.0*primes/n);
if (progress != temp)
{
String updateString;
updateString = "Progress to " + n + "th prime: "
+ (10 * progress) + "%\n";
// Update the UI thread with the DispatcherQueue.
dispatcherQueue.TryEnqueue(
Microsoft.UI.Dispatching.DispatcherQueuePriority.High,
() => UpdateUI(updateString));
}
}
}
// Return the nth prime number.
nthPrime = i;
});
// A reference to the work item is cached so that we can trigger a
// cancellation when the user presses the Cancel button.
m_workItem = asyncAction;
// The nth prime number to find.
const unsigned int n{ 9999 };
// A shared pointer to the result.
// We use a shared pointer to keep the result alive until the
// work is done.
std::shared_ptr<unsigned long> nthPrime = std::make_shared<unsigned long>(0);
// Simulates work by searching for the nth prime number. Uses a
// naive algorithm and counts 2 as the first prime number.
// Capture the DispatcherQueue before entering the background lambda.
auto dispatcherQueue{ Microsoft::UI::Dispatching::DispatcherQueue::GetForCurrentThread() };
// A reference to the work item is cached so that we can trigger a
// cancellation when the user presses the Cancel button.
m_workItem = Windows::System::Threading::ThreadPool::RunAsync(
[=, strongThis = get_strong()](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 updateStream;
updateStream << L"Progress to " << n << L"th prime: " << (10 * progress) << std::endl;
std::wstring updateString = updateStream.str();
// Update the UI thread with the DispatcherQueue.
dispatcherQueue.TryEnqueue(
Microsoft::UI::Dispatching::DispatcherQueuePriority::High,
[strongThis, updateString]()
{
strongThis->UpdateUI(updateString);
});
}
}
}
// Return the nth prime number.
*nthPrime = i;
});
// The nth prime number to find.
const unsigned int n = 9999;
// A shared pointer to the result.
// We use a shared pointer to keep the result alive until the
// work is done.
std::shared_ptr<unsigned long> nthPrime = std::make_shared<unsigned long>(0);
// Simulates work by searching for the nth prime number. Uses a
// naive algorithm and counts 2 as the first prime number.
auto workItem = ref new Windows::System::Threading::WorkItemHandler(
[this, n, nthPrime](IAsyncAction^ 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 == 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)
{
String^ updateString;
updateString = "Progress to " + n + "th prime: "
+ (10 * progress).ToString() + "%\n";
// Update the UI thread with the CoreDispatcher.
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::High,
ref new DispatchedHandler([this, updateString]()
{
UpdateUI(updateString);
}));
}
}
}
// Return the nth prime number.
*nthPrime = i;
});
auto asyncAction = ThreadPool::RunAsync(workItem);
// A reference to the work item is cached so that we can trigger a
// cancellation when the user presses the Cancel button.
m_workItem = asyncAction;
Po wywołaniu funkcji RunAsync element roboczy jest kolejkowany przez pulę wątków i uruchamiany po udostępnieniu wątku. Elementy robocze puli wątków są uruchamiane asynchronicznie i mogą być uruchamiane w dowolnej kolejności, więc upewnij się, że elementy robocze działają niezależnie.
Należy pamiętać, że element roboczy sprawdza właściwość IAsyncInfo.Status i kończy działanie, jeśli element roboczy został anulowany.
Obsługa uzupełniania elementu roboczego
Podaj procedurę obsługi ukończenia, ustawiając właściwość IAsyncAction.Completed elementu roboczego. Podaj delegata (można użyć funkcji lambda lub delegata) do obsługi ukończenia elementu roboczego. Na przykład użyj polecenia DispatcherQueue.TryEnqueue , aby uzyskać dostęp do wątku interfejsu użytkownika i wyświetlić wynik.
Poniższy przykład aktualizuje interfejs użytkownika z wynikiem elementu roboczego przesłanego w kroku 1:
asyncAction.Completed = new AsyncActionCompletedHandler(
(IAsyncAction asyncInfo, AsyncStatus asyncStatus) =>
{
if (asyncStatus == AsyncStatus.Canceled)
{
return;
}
String updateString;
updateString = "\n" + "The " + n + "th prime number is "
+ nthPrime + ".\n";
// Update the UI thread with the DispatcherQueue.
dispatcherQueue.TryEnqueue(
Microsoft.UI.Dispatching.DispatcherQueuePriority.High,
() => UpdateUI(updateString));
});
m_workItem.Completed(
[=, strongThis = get_strong()](Windows::Foundation::IAsyncAction const& asyncInfo, Windows::Foundation::AsyncStatus const& asyncStatus)
{
if (asyncStatus == Windows::Foundation::AsyncStatus::Canceled)
{
return;
}
std::wstringstream updateStream;
updateStream << std::endl << L"The " << n << L"th prime number is " << *nthPrime << std::endl;
std::wstring updateString = updateStream.str();
// Update the UI thread with the DispatcherQueue.
dispatcherQueue.TryEnqueue(
Microsoft::UI::Dispatching::DispatcherQueuePriority::High,
[strongThis, updateString]()
{
strongThis->UpdateUI(updateString);
});
});
Należy pamiętać, że program obsługi uzupełniania sprawdza, czy element roboczy został anulowany przed wysłaniem aktualizacji interfejsu użytkownika.
Podsumowanie i następne kroki
Więcej informacji można znaleźć w przykładach obsługi wątków dla Zestaw SDK do aplikacji systemu Windows na GitHubie.