Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
APIs importantes
Aprenda a trabalhar em um thread separado enviando um item de trabalho ao pool de threads. Use isso para manter uma interface do usuário responsiva ao concluir um trabalho que leva um tempo perceptível e usá-lo para concluir várias tarefas em paralelo.
Criar e enviar o item de trabalho
Crie um item de trabalho chamando RunAsync. Forneça um delegado para fazer o trabalho (você pode usar um lambda ou uma função delegada). Observe que RunAsync retorna um objeto IAsyncAction ; armazene esse objeto para uso na próxima etapa.
Três versões do RunAsync estão disponíveis para que você possa, opcionalmente, especificar a prioridade do item de trabalho e controlar se ele é executado simultaneamente com outros itens de trabalho.
O exemplo a seguir cria um item de trabalho e fornece um lambda para fazer o trabalho:
// 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;
Após a chamada para RunAsync, o item de trabalho é enfileirado pelo pool de threads e é executado quando um thread fica disponível. Os itens de trabalho do pool de threads são executados de forma assíncrona e podem ser executados em qualquer ordem, portanto, verifique se os itens de trabalho funcionam de forma independente.
Observe que o item de trabalho verifica a propriedade IAsyncInfo.Status e sai se o item de trabalho for cancelado.
Gerenciar a conclusão de item de trabalho
Forneça um manipulador de conclusão definindo a propriedade IAsyncAction.Completed do item de trabalho. Forneça um delegado (você pode usar um lambda ou uma função delegada) para lidar com a conclusão do item de trabalho. Por exemplo, use DispatcherQueue.TryEnqueue para acessar o thread da interface do usuário e mostrar o resultado.
O exemplo a seguir atualiza a interface do usuário com o resultado do item de trabalho enviado na etapa 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);
});
});
Observe que o manipulador de conclusão verifica se o item de trabalho foi cancelado antes de expedir uma atualização da interface do usuário.
Resumo e próximas etapas
Você pode aprender mais com os exemplos de threads do SDK do Aplicativo Windows no GitHub.
Tópicos relacionados:
Windows developer