Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
APIs importantes
Aprende a fazer trabalho num tópico separado submetendo um item de trabalho ao pool de threads. Usa isto para manter uma interface responsiva enquanto fazes trabalhos que demoram um tempo considerável, e usa-o para completar múltiplas tarefas em paralelo.
Crie e submeta o item de trabalho
Crie um item de trabalho chamando o RunAsync. Fornece um delegado para fazer o trabalho (podes usar uma função lambda ou delegar). Note que o RunAsync devolve um objeto IAsyncAction ; Armazene este objeto para uso na próxima etapa.
Estão disponíveis três versões do RunAsync para que possas opcionalmente especificar a prioridade do item de trabalho e controlar se este corre em simultâneo com outros itens de trabalho.
Observação
Os exemplos de código nesta secção utilizam a API UWP CoreDispatcher . Nas aplicações do WinUI 3, usa DispatcherQueue.TryEnqueue o from Microsoft.UI.Dispatching.DispatcherQueue para aceder ao tópico da interface e mostrar o progresso do item de trabalho. Consulte a visão geral do DispatcherQueue para mais detalhes.
O exemplo seguinte cria um item de trabalho e fornece uma função lambda para executar essa tarefa:
// 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.
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 CoreDispatcher.
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.High,
new DispatchedHandler(() =>
{
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.
// 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 CoreDispatcher.
Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync(
Windows::UI::Core::CoreDispatcherPriority::High,
Windows::UI::Core::DispatchedHandler([=]()
{
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 ao RunAsync, o item de trabalho é colocado em fila pelo pool de threads e executa-se quando um thread fica disponível. Os itens de trabalho do pool de threads correm de forma assíncrona e podem correr em qualquer ordem, por isso certifica-te de que os teus itens de trabalho funcionam de forma independente.
Tenha em atenção que o item de trabalho verifica a propriedade IAsyncInfo.Status, e termina se o item de trabalho for cancelado.
Tratar da conclusão do item de trabalho
Forneça um handler de completamento definindo a propriedade IAsyncAction.Completed do item de trabalho. Forneça um delegado (pode utilizar uma expressão lambda ou uma função delegada) para processar a conclusão de um item de trabalho. Por exemplo, use DispatcherQueue.TryEnqueue (WinUI 3) ou CoreDispatcher.RunAsync (UWP) para aceder ao tópico da interface e mostrar o resultado.
O exemplo seguinte atualiza a interface com o resultado do item de trabalho submetido no passo 1:
asyncAction->Completed = ref new AsyncActionCompletedHandler(
[this, n, nthPrime](IAsyncAction^ asyncInfo, AsyncStatus asyncStatus)
{
if (asyncStatus == AsyncStatus::Canceled)
{
return;
}
String^ updateString;
updateString = "\n" + "The " + n + "th prime number is "
+ (*nthPrime).ToString() + ".\n";
// Update the UI thread with the CoreDispatcher.
CoreApplication::MainView->CoreWindow->Dispatcher->RunAsync(
CoreDispatcherPriority::High,
ref new DispatchedHandler([this, updateString]()
{
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 CoreDispatcher.
Windows::ApplicationModel::Core::CoreApplication::MainView().CoreWindow().Dispatcher().RunAsync(
Windows::UI::Core::CoreDispatcherPriority::High,
Windows::UI::Core::DispatchedHandler([=]()
{
strongThis->UpdateUI(updateString);
}));
});
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 CoreDispatcher.
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(
CoreDispatcherPriority.High,
new DispatchedHandler(()=>
{
UpdateUI(updateString);
}));
});
Note que o handler de conclusão verifica se o item de trabalho foi cancelado antes de despachar uma atualização da interface.
Resumo e próximos passos
Pode obter mais informações ao transferir o código deste guia de início rápido no exemplo de criação de um item de trabalho do ThreadPool, concebido para o Windows 8.1, e reutilizar o código-fonte numa aplicação para Windows 10.
Tópicos relacionados
Windows developer