Postupy: Dokončení asynchronních operací s použitím knihovny WRL
Tento dokument ukazuje, jak použít Knihovna šablon C++ prostředí Windows Runtime (WRL) ke spuštění asynchronní operace a provedení práce, po dokončení operace.
Tento dokument obsahuje dva příklady.První příklad spuštění asynchronního časovače a čekat na vypršení časovače.V tomto příkladu zadáte asynchronní akce při vytváření objektu timer.Druhý příklad spuštění pracovního podprocesu pozadí.Tento příklad ukazuje, jak pracovat s prostředí Windows Runtime metodu, která vrací IAsyncInfo rozhraní.Zpětného volání funkce je důležitou součástí oba příklady, protože umožňuje jim určit obslužnou rutinu události pro zpracování výsledků asynchronní operace.
Jednodušší příklad, který vytvoří instanci komponenty a načte hodnotu vlastnosti, viz Postupy: Aktivace a používání komponent prostředí Windows Runtime s použitím knihovny WRL.
Tip
Tyto příklady slouží lambda výrazy k definování zpětná volání.Můžete také použít funkce objektů (functors), funkce ukazatelů nebo std::function objekty.Další informace o lambda výrazy jazyka C++, naleznete v Výrazy lambda v jazyce C++.
Příklad: Práce s časovačem
Následující kroky spuštění asynchronního časovače a čekat na vypršení časovače.Kompletní příklad postupuje.
![]() |
---|
Ačkoli obvykle používají WRL v Windows Store app, tento příklad používá aplikace konzoly pro ilustraci.Funguje jako wprintf_s nejsou k dispozici Windows Store app.Další informace o typech a funkce, které lze použít v Windows Store app, viz není podporována /ZW funkcí CRT a aplikacím Win32 a COM pro Windows Store. |
Zahrnout (#include) všechny požadované prostředí Windows Runtime, WRL, nebo záhlaví knihovny standard C++.
#include <Windows.Foundation.h> #include <Windows.System.Threading.h> #include <wrl/event.h> #include <stdio.h> #include <Objbase.h> using namespace ABI::Windows::Foundation; using namespace ABI::Windows::System::Threading; using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers;
Windows.System.Threading.h prohlašuje typy, které jsou nutné pro použití asynchronního časovače.
Doporučujeme vám využít using namespace v souboru CPP pro čitelnost kódu.
Inicializace prostředí Windows Runtime.
// Initialize the Windows Runtime. RoInitializeWrapper initialize(RO_INIT_MULTITHREADED); if (FAILED(initialize)) { return PrintError(__LINE__, initialize); }
Vytvořit aktivační výrobce ABI::Windows::System::Threading::IThreadPoolTimer rozhraní.
// Get the activation factory for the IThreadPoolTimer interface. ComPtr<IThreadPoolTimerStatics> timerFactory; HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
prostředí Windows Runtime Používá k identifikaci typů plně kvalifikované názvy.RuntimeClass_Windows_System_Threading_ThreadPoolTimer Parametr je řetězec, který je poskytován prostředí Windows Runtime a obsahuje název požadovaná třída.
Vytvoření události objekt, který synchronizuje zpětné volání timer hlavní aplikaci.
// Create an event that is set after the timer callback completes. We later use this event to wait for the timer to complete. // This event is for demonstration only in a console app. In most apps, you typically don't wait for async operations to complete. Event timerCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS)); hr = timerCompleted.IsValid() ? S_OK : HRESULT_FROM_WIN32(GetLastError()); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
[!POZNÁMKA]
Tato událost je pro ukázku pouze jako součást aplikace konzoly.Tento příklad používá událost k zajištění, že asynchronní operace dokončena před ukončí aplikace.Ve většině aplikací je obvykle nečeká na dokončení asynchronní operace.
Vytvořit IThreadPoolTimer objekt, který vyprší po dvou sekundách.Použití Callback funkce pro vytvoření obslužné rutiny události ( ABI::Windows::System::Threading::ITimerElapsedHandler objekt).
// Create a timer that prints a message after 2 seconds. TimeSpan delay; delay.Duration = 20000000; // 2 seconds. auto callback = Callback<ITimerElapsedHandler>([&timerCompleted](IThreadPoolTimer* timer) -> HRESULT { wprintf_s(L"Timer fired.\n"); TimeSpan delay; HRESULT hr = timer->get_Delay(&delay); if (SUCCEEDED(hr)) { wprintf_s(L"Timer duration: %2.2f seconds.\n", delay.Duration / 10000000.0); } // Set the completion event and return. SetEvent(timerCompleted.Get()); return hr; }); hr = callback ? S_OK : E_OUTOFMEMORY; if (FAILED(hr)) { return PrintError(__LINE__, hr); } ComPtr<IThreadPoolTimer> timer; hr = timerFactory->CreateTimer(callback.Get(), delay, &timer); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
Tisk zprávy do konzoly a počkejte na dokončení zpětného volání časovače.Všechny ComPtr a RAII objekty ponechat oboru automaticky uvolněna.
// Print a message and wait for the timer callback to complete. wprintf_s(L"Timer started.\nWaiting for timer...\n"); // Wait for the timer to complete. WaitForSingleObjectEx(timerCompleted.Get(), INFINITE, FALSE); // All smart pointers and RAII objects go out of scope here.
Zde je kompletní příklad:
// wrl-consume-async.cpp
// compile with: runtimeobject.lib
#include <Windows.Foundation.h>
#include <Windows.System.Threading.h>
#include <wrl/event.h>
#include <stdio.h>
#include <Objbase.h>
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::System::Threading;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
// Prints an error string for the provided source code line and HRESULT
// value and returns the HRESULT value as an int.
int PrintError(unsigned int line, HRESULT hr)
{
wprintf_s(L"ERROR: Line:%d HRESULT: 0x%X\n", line, hr);
return hr;
}
int wmain()
{
// Initialize the Windows Runtime.
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
if (FAILED(initialize))
{
return PrintError(__LINE__, initialize);
}
// Get the activation factory for the IThreadPoolTimer interface.
ComPtr<IThreadPoolTimerStatics> timerFactory;
HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Create an event that is set after the timer callback completes. We later use this event to wait for the timer to complete.
// This event is for demonstration only in a console app. In most apps, you typically don't wait for async operations to complete.
Event timerCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));
hr = timerCompleted.IsValid() ? S_OK : HRESULT_FROM_WIN32(GetLastError());
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Create a timer that prints a message after 2 seconds.
TimeSpan delay;
delay.Duration = 20000000; // 2 seconds.
auto callback = Callback<ITimerElapsedHandler>([&timerCompleted](IThreadPoolTimer* timer) -> HRESULT
{
wprintf_s(L"Timer fired.\n");
TimeSpan delay;
HRESULT hr = timer->get_Delay(&delay);
if (SUCCEEDED(hr))
{
wprintf_s(L"Timer duration: %2.2f seconds.\n", delay.Duration / 10000000.0);
}
// Set the completion event and return.
SetEvent(timerCompleted.Get());
return hr;
});
hr = callback ? S_OK : E_OUTOFMEMORY;
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
ComPtr<IThreadPoolTimer> timer;
hr = timerFactory->CreateTimer(callback.Get(), delay, &timer);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Print a message and wait for the timer callback to complete.
wprintf_s(L"Timer started.\nWaiting for timer...\n");
// Wait for the timer to complete.
WaitForSingleObjectEx(timerCompleted.Get(), INFINITE, FALSE);
// All smart pointers and RAII objects go out of scope here.
}
/*
Output:
Timer started.
Waiting for timer...
Timer fired.
Timer duration: 2.00 seconds.
*/
Probíhá kompilace kódu
Kompilovat kód, zkopírujte jej a vložte do projektu sady Visual Studio nebo vložit do souboru s názvem wrl spotřebovat async.cpp a potom spusťte následující příkaz v okně Příkazový řádek Visual Studio.
cl.exe wrl-consume-async.cpp runtimeobject.lib
Příklad: Práce s podprocesem na pozadí
Následující postup spuštění pracovního podprocesu a definovat akci, kterou provádí toto vlákno.Kompletní příklad postupuje.
Tip
Tento příklad ukazuje, jak pracovat ABI::Windows::Foundation::IAsyncAction rozhraní.Tento vzor lze použít na libovolném rozhraní, které implementuje IAsyncInfo: IAsyncAction, IAsyncActionWithProgress, IAsyncOperation, a IAsyncOperationWithProgress.
Zahrnout (#include) všechny požadované prostředí Windows Runtime, WRL, nebo záhlaví knihovny standard C++.
#include <Windows.Foundation.h> #include <Windows.System.Threading.h> #include <wrl/event.h> #include <stdio.h> #include <Objbase.h> using namespace ABI::Windows::Foundation; using namespace ABI::Windows::System::Threading; using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers;
Windows.System.Threading.h prohlašuje typy, které jsou povinny používat pracovní podproces.
Doporučujeme použít using namespace v souboru CPP pro čitelnost kódu.
Inicializace prostředí Windows Runtime.
// Initialize the Windows Runtime. RoInitializeWrapper initialize(RO_INIT_MULTITHREADED); if (FAILED(initialize)) { return PrintError(__LINE__, initialize); }
Vytvořit aktivační výrobce ABI::Windows::System::Threading::IThreadPoolStatics rozhraní.
// Get the activation factory for the IThreadPoolStatics interface. ComPtr<IThreadPoolStatics> threadPool; HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(), &threadPool); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
Vytvoření události objekt, který synchronizuje skončení pracovní podproces hlavní aplikaci.
// Create an event that is set after the timer callback completes. We later use this event to wait for the timer to complete. // This event is for demonstration only in a console app. In most apps, you typically don't wait for async operations to complete. Event threadCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS)); hr = threadCompleted.IsValid() ? S_OK : HRESULT_FROM_WIN32(GetLastError()); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
[!POZNÁMKA]
Tato událost je pro ukázku pouze jako součást aplikace konzoly.Tento příklad používá událost k zajištění, že asynchronní operace dokončena před ukončí aplikace.Ve většině aplikací je obvykle nečeká na dokončení asynchronní operace.
Volat IThreadPoolStatics::RunAsync metoda vytvořit pracovní podproces.Použití Callback funkce pro definování akce.
wprintf_s(L"Starting thread...\n"); // Create a thread that computes prime numbers. ComPtr<IAsyncAction> asyncAction; hr = threadPool->RunAsync(Callback<IWorkItemHandler>([&threadCompleted](IAsyncAction* asyncAction) -> HRESULT { // Print a message. const unsigned int start = 0; const unsigned int end = 100000; unsigned int primeCount = 0; for (int n = start; n < end; n++) { if (IsPrime(n)) { primeCount++; } } wprintf_s(L"There are %u prime numbers from %u to %u.\n", primeCount, start, end); // Set the completion event and return. SetEvent(threadCompleted.Get()); return S_OK; }).Get(), &asyncAction); if (FAILED(hr)) { return PrintError(__LINE__, hr); }
IsPrime Funkce je definována v úplném příkladu, který následuje.
Tisk zprávy do konzoly a čekají na vlákno dokončí.Všechny ComPtr a RAII objekty ponechat oboru automaticky uvolněna.
// Print a message and wait for the thread to complete. wprintf_s(L"Waiting for thread...\n"); // Wait for the thread to complete. WaitForSingleObjectEx(threadCompleted.Get(), INFINITE, FALSE); wprintf_s(L"Finished.\n"); // All smart pointers and RAII objects go out of scope here.
Zde je kompletní příklad:
// wrl-consume-asyncOp.cpp
// compile with: runtimeobject.lib
#include <Windows.Foundation.h>
#include <Windows.System.Threading.h>
#include <wrl/event.h>
#include <stdio.h>
#include <Objbase.h>
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::System::Threading;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
// Prints an error string for the provided source code line and HRESULT
// value and returns the HRESULT value as an int.
int PrintError(unsigned int line, HRESULT hr)
{
wprintf_s(L"ERROR: Line:%d HRESULT: 0x%X\n", line, hr);
return hr;
}
// Determines whether the input value is prime.
bool IsPrime(int n)
{
if (n < 2)
{
return false;
}
for (int i = 2; i < n; ++i)
{
if ((n % i) == 0)
{
return false;
}
}
return true;
}
int wmain()
{
// Initialize the Windows Runtime.
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
if (FAILED(initialize))
{
return PrintError(__LINE__, initialize);
}
// Get the activation factory for the IThreadPoolStatics interface.
ComPtr<IThreadPoolStatics> threadPool;
HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_System_Threading_ThreadPool).Get(), &threadPool);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Create an event that is set after the timer callback completes. We later use this event to wait for the timer to complete.
// This event is for demonstration only in a console app. In most apps, you typically don't wait for async operations to complete.
Event threadCompleted(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));
hr = threadCompleted.IsValid() ? S_OK : HRESULT_FROM_WIN32(GetLastError());
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
wprintf_s(L"Starting thread...\n");
// Create a thread that computes prime numbers.
ComPtr<IAsyncAction> asyncAction;
hr = threadPool->RunAsync(Callback<IWorkItemHandler>([&threadCompleted](IAsyncAction* asyncAction) -> HRESULT
{
// Print a message.
const unsigned int start = 0;
const unsigned int end = 100000;
unsigned int primeCount = 0;
for (int n = start; n < end; n++)
{
if (IsPrime(n))
{
primeCount++;
}
}
wprintf_s(L"There are %u prime numbers from %u to %u.\n", primeCount, start, end);
// Set the completion event and return.
SetEvent(threadCompleted.Get());
return S_OK;
}).Get(), &asyncAction);
if (FAILED(hr))
{
return PrintError(__LINE__, hr);
}
// Print a message and wait for the thread to complete.
wprintf_s(L"Waiting for thread...\n");
// Wait for the thread to complete.
WaitForSingleObjectEx(threadCompleted.Get(), INFINITE, FALSE);
wprintf_s(L"Finished.\n");
// All smart pointers and RAII objects go out of scope here.
}
/*
Output:
Starting thread...
Waiting for thread...
There are 9592 prime numbers from 0 to 100000.
Finished.
*/
Probíhá kompilace kódu
Kompilovat kód, zkopírujte jej a vložte do projektu sady Visual Studio nebo vložit do souboru s názvem wrl spotřebovat asyncOp.cpp a potom spusťte následující příkaz v okně Příkazový řádek Visual Studio.
cl.exe wrl-consume-asyncOp.cpp runtimeobject.lib