Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Als Alternative zum Beispielcode in diesem Thema gibt es den Quellcode für eine produktionsfähige Version einer Implementierung der Aufgabenabschlussquelle im cpp-async-GitHub-Repository.
In diesem Thema wird veranschaulicht, wie Sie Ihre eigene Abschlussquellklasse erstellen und nutzen können, ähnlich wie die TaskCompletionSource von .NET.
Quellcode für das completion_source-Beispiel
Der Code in der nachstehenden Auflistung wird als Beispiel angeboten. Der Zweck besteht darin, zu veranschaulichen, wie Sie Ihre eigene Version davon schreiben können. Zum Beispiel fallen die Unterstützung für Abbruchvorgänge und die Fehlerweitergabe nicht in den Umfang dieses Beispiels.
#include <winrt/base.h>
#include <windows.h>
template <typename T>
struct completion_source
{
completion_source()
{
m_signal.attach(::CreateEvent(nullptr, true, false, nullptr));
}
void set(T const& value)
{
m_value = value;
::SetEvent(m_signal.get());
}
bool await_ready() const noexcept
{
return ::WaitForSingleObject(m_signal.get(), 0) == 0;
}
void await_suspend(std::experimental::coroutine_handle<> resume)
{
m_wait.attach(winrt::check_pointer(::CreateThreadpoolWait(callback, resume.address(), nullptr)));
::SetThreadpoolWait(m_wait.get(), m_signal.get(), nullptr);
}
T await_resume() const noexcept
{
return m_value;
}
private:
static void __stdcall callback(PTP_CALLBACK_INSTANCE, void* context, PTP_WAIT, TP_WAIT_RESULT) noexcept
{
std::experimental::coroutine_handle<>::from_address(context)();
}
struct wait_traits
{
using type = PTP_WAIT;
static void close(type value) noexcept
{
::CloseThreadpoolWait(value);
}
static constexpr type invalid() noexcept
{
return nullptr;
}
};
winrt::handle m_signal;
winrt::handle_type<wait_traits> m_wait;
T m_value{};
};
Die Fertigstellung in eine separate Coroutine auslagern
In diesem Abschnitt wird ein Anwendungsfall für completion_source veranschaulicht. Erstellen Sie ein neues Projekt in Visual Studio basierend auf der Projektvorlage Windows Konsolenanwendung (C++/WinRT) und fügen Sie die folgende Codeauflistung main.cpp ein (erweitern sie die Definition von completion_source basierend auf der Auflistung im vorherigen Abschnitt).
// main.cpp
#include "pch.h"
#include <winrt/base.h>
#include <windows.h>
template <typename T>
struct completion_source
{
... // Paste the listing of completion_source here.
}
using namespace std::literals;
using namespace winrt;
using namespace Windows::Foundation;
fire_and_forget CompleteAfterFiveSecondsAsync(completion_source<bool>& completionSource)
{
co_await 5s;
completionSource.set(true);
}
IAsyncAction CompletionSourceExample1Async()
{
completion_source<bool> completionSource;
CompleteAfterFiveSecondsAsync(completionSource);
co_await completionSource;
}
int main()
{
auto asyncAction { CompletionSourceExample1Async() };
puts("waiting");
asyncAction.get();
puts("done");
}
Kapseln Sie eine completion_source in einer Klasse und geben Sie einen Wert zurück
Im nächsten Beispiel wird eine einfache App-Klasse verwendet, um eine completion_source zu kapseln und einen Wert zurückzugeben, wenn sie abgeschlossen ist. Erstellen Sie ein neues Projekt in Visual Studio basierend auf der Projektvorlage Windows Konsolenanwendung (C++/WinRT) und fügen Sie die folgende Codeauflistung main.cpp ein (erweitern sie die Definition von completion_source basierend auf der Auflistung im vorherigen Abschnitt).
// main.cpp
#include "pch.h"
#include <winrt/base.h>
#include <windows.h>
template <typename T>
struct completion_source
{
... // Paste the listing of completion_source here.
}
using namespace std::literals;
using namespace winrt;
using namespace Windows::Foundation;
struct App
{
completion_source<winrt::hstring> m_completionSource;
IAsyncOperation<winrt::hstring> CompletionSourceExample2Async()
{
co_return co_await m_completionSource;
}
winrt::fire_and_forget CompleteAfterFiveSecondsAsync()
{
co_await 5s;
m_completionSource.set(L"Hello, World!");
}
};
int main()
{
App app;
auto asyncAction{ app.CompletionSourceExample2Async() };
app.CompleteAfterFiveSecondsAsync();
puts("waiting");
auto message = asyncAction.get();
printf("%ls\n", message.c_str());
}
Zugehörige Themen
Windows developer