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 produktionsbereite Version einer Implementierung für die Taskausführung im GitHub-Repository cpp-async.
In diesem Thema wird veranschaulicht, wie Sie eine eigene Abschlussquellklasse ähnlich TaskCompletionSource von .NET erstellen und verwenden können.
Der Code in der folgenden Auflistung dient als Beispiel. Der Zweck besteht darin, zu veranschaulichen, wie Sie Ihre eigene Version davon schreiben können. Die Unterstützung für die Abbruch- und Fehlerverteilung befindet sich beispielsweise außerhalb des Umfangs 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{};
};
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 in main.cpp
ein (indem Sie die Definition von completion_source basierend auf der Auflistung im vorherigen Abschnitt erweitern).
// 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");
}
Im nächsten Beispiel wird eine einfache App-Klasse verwendet, um ein completion_source-Objekt zu kapseln und nach Abschluss des Vorgangs einen Wert zurückzugeben. Erstellen Sie ein neues Projekt in Visual Studio basierend auf der Projektvorlage Windows-Konsolenanwendung (C++/WinRT) , und fügen Sie die folgende Codeauflistung in main.cpp
ein (indem Sie die Definition von completion_source basierend auf der Auflistung im vorherigen Abschnitt erweitern).
// 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());
}