php網(wǎng)站開發(fā)實例教程簡介關(guān)鍵詞優(yōu)化怎么優(yōu)化
本主題演示如何創(chuàng)作和使用自己的完成源類,類似于 .NET 的?TaskCompletionSource。
completion_source 示例的源代碼
下面的列表中的代碼作為示例提供。 其目的是說明如何編寫自己的版本。 例如,支持取消和錯誤傳播不在此示例的范圍內(nèi)。
#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{};
};
將完成卸載到單獨的協(xié)同程序
本部分演示 completion_source 的一個用例。 在 Visual Studio 中創(chuàng)建一個基于 Windows 控制臺應(yīng)用程序 (C++/WinRT) 項目模板的新項目,然后將以下代碼清單粘貼到?main.cpp
(根據(jù)上一節(jié)中的列表展開 completion_source 的定義)。
// main.cpp
#include "pch.h"#include <winrt/base.h>
#include <windows.h>template <typename T>
struct completion_source
{//構(gòu)造函數(shù)completion_source(){m_signal.attach(::CreateEvent(nullptr, true, false, nullptr));}void set(T const& value){m_value = value;::SetEvent(m_signal.get());//將指定的事件對象設(shè)置為信號狀態(tài)。}//準備bool await_ready() const noexcept{return ::WaitForSingleObject(m_signal.get(), 0) == 0;//等待指定的對象處于信號狀態(tài)或超時間隔已過。若要進入可警報等待狀態(tài),請使用 WaitForSingleObjectEx 函數(shù)。 若要等待多個對象,請使用 WaitForMultipleObjects。}//暫停void await_suspend(std::experimental::coroutine_handle<> resume){//CreateThreadpoolWait:創(chuàng)建新的等待對象。//參數(shù)1:[in] pfnwa 等待完成或超時時要調(diào)用的回調(diào)函數(shù)。//參數(shù)2:[in, out, optional] pv 要傳遞給回調(diào)函數(shù)的可選應(yīng)用程序定義數(shù)據(jù)。//參數(shù)3:[in, optional] pcbe 定義執(zhí)行回調(diào)的環(huán)境 的TP_CALLBACK_ENVIRON 結(jié)構(gòu)。 InitializeThreadpoolEnvironment 函數(shù)返回此結(jié)構(gòu)。如果此參數(shù)為 NULL,則回調(diào)在默認回調(diào)環(huán)境中執(zhí)行。 有關(guān)詳細信息,請參閱 InitializeThreadpoolEnvironment。m_wait.attach(winrt::check_pointer(::CreateThreadpoolWait(callback, resume.address(), nullptr)));::SetThreadpoolWait(m_wait.get(), m_signal.get(), nullptr);//設(shè)置 wait 對象,替換上一個等待對象(如果有)。 工作線程在句柄發(fā)出信號后或在指定的超時過期后調(diào)用 wait 對象的回調(diào)函數(shù)。}//返回m_valueT await_resume() const noexcept{return m_value;}private://回調(diào)函數(shù)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;//釋放指定的等待對象valuestatic void close(type value) noexcept //noexcept:指定某個函數(shù)是否可能會引發(fā)異常{::CloseThreadpoolWait(value);//釋放指定的等待對象。}//返回空指針static constexpr type invalid() noexcept //constexpr:它表示 constant(常數(shù))表達式。 與 const 一樣,它可以應(yīng)用于變量:如果任何代碼試圖 modify(修改)該值,將引發(fā)編譯器錯誤。{return nullptr; }};winrt::handle m_signal; //會話句柄winrt::handle_type<wait_traits> m_wait;T m_value{};
};using namespace winrt;
using namespace Windows::Foundation;
using namespace std::literals;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");
}
?
將 completion_source 封裝在類中,并返回一個值
在下一個示例中,使用簡單的 App 類封裝 completion_source,并在完成時返回值。 在 Visual Studio 中創(chuàng)建一個基于 Windows 控制臺應(yīng)用程序 (C++/WinRT) 項目模板的新項目,然后將以下代碼清單粘貼到?main.cpp
(根據(jù)上一節(jié)中的列表展開 completion_source 的定義)。
// main.cpp
#include "pch.h"#include <winrt/base.h>
#include <windows.h>template <typename T>
struct completion_source
{//構(gòu)造函數(shù)completion_source(){m_signal.attach(::CreateEvent(nullptr, true, false, nullptr));}void set(T const& value){m_value = value;::SetEvent(m_signal.get());//將指定的事件對象設(shè)置為信號狀態(tài)。}//準備bool await_ready() const noexcept{return ::WaitForSingleObject(m_signal.get(), 0) == 0;//等待指定的對象處于信號狀態(tài)或超時間隔已過。若要進入可警報等待狀態(tài),請使用 WaitForSingleObjectEx 函數(shù)。 若要等待多個對象,請使用 WaitForMultipleObjects。}//暫停void await_suspend(std::experimental::coroutine_handle<> resume){//CreateThreadpoolWait:創(chuàng)建新的等待對象。//參數(shù)1:[in] pfnwa 等待完成或超時時要調(diào)用的回調(diào)函數(shù)。//參數(shù)2:[in, out, optional] pv 要傳遞給回調(diào)函數(shù)的可選應(yīng)用程序定義數(shù)據(jù)。//參數(shù)3:[in, optional] pcbe 定義執(zhí)行回調(diào)的環(huán)境 的TP_CALLBACK_ENVIRON 結(jié)構(gòu)。 InitializeThreadpoolEnvironment 函數(shù)返回此結(jié)構(gòu)。如果此參數(shù)為 NULL,則回調(diào)在默認回調(diào)環(huán)境中執(zhí)行。 有關(guān)詳細信息,請參閱 InitializeThreadpoolEnvironment。m_wait.attach(winrt::check_pointer(::CreateThreadpoolWait(callback, resume.address(), nullptr)));::SetThreadpoolWait(m_wait.get(), m_signal.get(), nullptr);//設(shè)置 wait 對象,替換上一個等待對象(如果有)。 工作線程在句柄發(fā)出信號后或在指定的超時過期后調(diào)用 wait 對象的回調(diào)函數(shù)。}//返回m_valueT await_resume() const noexcept{return m_value;}private://回調(diào)函數(shù)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;//釋放指定的等待對象valuestatic void close(type value) noexcept //noexcept:指定某個函數(shù)是否可能會引發(fā)異常{::CloseThreadpoolWait(value);//釋放指定的等待對象。}//返回空指針static constexpr type invalid() noexcept //constexpr:它表示 constant(常數(shù))表達式。 與 const 一樣,它可以應(yīng)用于變量:如果任何代碼試圖 modify(修改)該值,將引發(fā)編譯器錯誤。{return nullptr; }};winrt::handle m_signal; //會話句柄winrt::handle_type<wait_traits> m_wait;T m_value{};
};using namespace winrt;
using namespace Windows::Foundation;
using namespace std::literals;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());
}
?