The Windows::Foundation Windows Runtime namespace contains four types of asynchronous operation object.
- IAsyncAction,
- IAsyncActionWithProgress
- IAsyncOperation
- IAsyncOperationWithProgress
在使用asynchronous Windows function時有2種方式
- blocking
- non-blocking
blocking適合用在console program或是background thread,不適合用在UI thread.
*********************************
coroutine介紹
*********************************
C++/WinRT 整合了 C++ coroutines into the programming model to provide a natural way to cooperatively wait for a result.
只要在function前宣告成上述提到的4種asynchronous operation object,即為coroutines。如下ProcessFeedAsync
IAsyncAction ProcessFeedAsync()
{
Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;
SyndicationFeed syndicationFeed{ co_await syndicationClient.RetrieveFeedAsync(rssFeedUri) };
print_function();
}
下例即為如何呼叫此coroutine:
int main
{
auto processOp{ ProcessFeedAsync() };
processOp.get();
}
MS對coroutine的解釋:
A coroutine is a function that can be suspended and resumed. In the ProcessFeedAsync coroutine above, when the co_await statement is reached, the coroutine asynchronously initiates the RetrieveFeedAsync call and then it immediately suspends itself and returns control back to the caller (which is main in the example above). main can then continue to do work while the feed is being retrieved and printed. When that's done (when the RetrieveFeedAsync call completes), the ProcessFeedAsync coroutine resumes at the next statement.
*********************************
coroutine回傳值
*********************************
coroutine可以回傳Windows Runtime type,如上。也可以回傳非Windows Runtime type,如concurrency::task. 範例如下
concurrency::task
{
return concurrency::create_task([]
{
Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;
SyndicationFeed syndicationFeed{ syndicationClient.RetrieveFeedAsync(rssFeedUri).get() };
return std::wstring{ syndicationFeed.Items().GetAt(0).Title().Text() };
});
}
int main()
{
winrt::init_apartment();
auto firstTitleOp{ RetrieveFirstTitleAsync() };
// Do other work here.
std::wcout << firstTitleOp.get() << std::endl;
}
*********************************
coroutine參數
*********************************
如果需要在coroutine中傳遞參數,要用const,以確保thread safe.
*********************************
coroutine的thread
*********************************
coroutine在碰到co_await, co_return, or co_yield時會rutern。
但如果在coroutine裡面沒有機會使用到這幾個時,可以直接使用
co_await winrt::resume_background();
這樣可以讓自己被丟到system thread pool,返回caller的thread,然後讓system啟動一個thread來完成自己的coroutine.
然而使用co_await winrt::resume_foreground(UI_thread)可以讓自己的thread回到UI thread,這個方式可以用來update UI.
值得注意的是在suspension點之後,原來的thread可能會消失不見,resume之後可能會是另一條thread來執行。但是如果我們使用的是Windows Runtime type (IAsyncXXX)的話,C++/WinRT會自動幫我們處理。C++/WinRT會在suspension之前先紀錄calling context,等到resume時會檢查並確保是在calling context. 如果不是使用(IAsyncXXX)的話,請記得確認此library有提供這個技術。
*********************************
Canceling an asychronous operation, and cancellation callbacks
*********************************
使用 IAsyncXXX.Cancel()來取消一個async operation.
或用 IAsyncXXX.callback()來註冊取消一個async operation之後要執行的function.
*********************************
Reporting progress
*********************************
使用 IAsyncActionWithProgress或IAsyncOperationWithProgress來回報進度。
*********************************
Fire and forget
*********************************
宣告coroutine為winrt::fire_and_forget,即為不等待結束。