我正在通過msdn(link)上的「教程:使用C++創建您的第一個Metro風格應用程序」。很快進入它的「第二部分」,我遇到了一個錯誤。我正在使用Visual Studio 2012 Release Candidate(最新版本)在Windows 8 VM Release Preview(5月31日)上運行此操作。C++ Metro應用程序教程 - 任務延續編譯錯誤
在添加3個新的metro頁面,ItemsPage,SplitPage和新的「DetailPage」之後,我所在的位置在代碼部分。添加這些都很好,但是當我添加的代碼下方,在標有節「要修改初始化數據模型的異步代碼」,它生成以下錯誤的兩個副本:
error C2893: Failed to specialize function template ''unknown-type' Concurrency::details::_VoidReturnTypeHelper(_Function,int,...)' c:\program files (x86)\microsoft visual studio 11.0\vc\include\ppltasks.h 404 1 SimpleBlogReader
然後我拿出來自該部分的所有代碼,並開始一次添加一塊,以找出錯誤「真正」的位置,因爲我顯然沒有修改該標準頭文件。事實證明,它在任務鏈在App::InitDataSource
方法:
SyndicationClient^ client = ref new SyndicationClient();
for(wstring url : urls)
{
// Create the async operation.
// feedOp is an IAsyncOperationWithProgress<SyndicationFeed^, RetrievalProgress>^
auto feedUri = ref new Uri(ref new String(url.c_str()));
auto feedOp = client->RetrieveFeedAsync(feedUri);
// Create the task object and pass it the async operation.
// SyndicationFeed^ is the type of the return value
// that the feedOp operation will eventually produce.
// Then, initialize a FeedData object with the feed info. Each
// operation is independent and does not have to happen on the
// UI thread. Therefore, we specify use_arbitrary.
create_task(feedOp).then([this] (SyndicationFeed^ feed) -> FeedData^
{
return GetFeedData(feed);
}, concurrency::task_continuation_context::use_arbitrary())
// Append the initialized FeedData object to the list
// that is the data source for the items collection.
// This has to happen on the UI thread. By default, a .then
// continuation runs in the same apartment thread that it was called on.
// Because the actions will be synchronized for us, we can append
// safely to the Vector without taking an explicit lock.
.then([fds] (FeedData^ fd)
{
fds->Append(fd);
// Write to VS output window in debug mode only. Requires <windows.h>.
OutputDebugString(fd->Title->Data());
OutputDebugString(L"\r\n");
})
// The last continuation serves as an error handler. The
// call to get() will surface any exceptions that were raised
// at any point in the task chain.
.then([this] (concurrency::task<SyndicationFeed^> t)
{
try
{
t.get();
}
// SyndicationClient throws E_INVALIDARG
// if a URL contains illegal characters.
catch(Platform::InvalidArgumentException^ e)
{
// TODO handle error. For example purposes
// we just output error to console.
OutputDebugString(e->Message->Data());
}
}); //end task chain
我拿出lambda表達式一次一個(和放在分號所以它會編譯),如果我有前兩個,這很好,但鏈中的最後一個導致錯誤。但如果我只是最後一個,它編譯。或者如果我用它編譯的第一個和第三個來完成它。或者只有前兩個。
問題是第二個lambda?頭文件庫對void返回類型感到困惑嗎?或者是別的什麼?根據這個理論,我將「最終」處理程序聲明修改爲:
// The last continuation serves as an error handler. The
// call to get() will surface any exceptions that were raised
// at any point in the task chain.
.then([this] (concurrency::task<void> t)
現在編譯。但根據msdn的文檔(here),這是正確的嗎?有該網頁上稱爲節「基於價值的對戰基於任務的延續」,也就是複製如下:
給定一個任務對象,其返回類型爲T,則可以提供 T型或任務的價值它的繼續任務。類型T需要 的延續被稱爲基於價值的延續。當先行任務 完成且沒有錯誤且未取消時,將計劃執行基於值的 延續。以 類型任務作爲其參數的延續稱爲基於任務的延續。 A 基於任務的延續總是安排在 先行任務完成時執行,即使先前任務被取消或 引發異常。然後你可以調用task :: get來獲得 的前面任務的結果。如果先行任務被取消,task :: get throws concurrency :: task_canceled。如果先行任務拋出異常,則task :: get將拋出異常。當其先行任務 取消時,基於任務的 延續未標記爲已取消。
這是說,對錯誤處理的最終延續應該是最終.then
延續的類型,還是原來的create_task
的類型?如果這是最後的(正如我上面用void
所做的那樣),這個延續是否會實際處理所有以上的錯誤,或者只是最後的.then
調用的錯誤?
這是「解決」他們的例子的正確方法嗎?或不?
我要求刪除這個問題,事實證明這是由於本教程無法跟上測試版的編譯器。這種差距不再存在,目前的教程工作100%。 –