问题:当我想渲染异步检索的传入数据时,我崩溃了。
应用程序启动并使用XAML显示一些对话框。一旦用户填写他们的数据并单击登录按钮,XAML类就会有一个工作者类的实例,它为我执行HTTP操作(使用IXMLHTTPRequest2异步)。当应用程序成功登录到Web服务器时,我的.then()块会触发,我会对我的主xaml类进行回调以对资产进行一些渲染。
我总是在委托中遇到崩溃(主要的XAML类),这让我相信我不能使用这种方法(纯虚拟类和回调)来更新我的UI。我想我无意中试图从错误的线程做一些非法的事情,这是异步调用的副产品。
是否有更好或不同的方式我应该通知主XAML类它是时候更新它的UI了?我来自iOS世界,我可以使用NotificationCenter。
现在,我看到微软在这里有自己的委托类型:http://msdn.microsoft.com/en-us/library/windows/apps/hh755798.aspx
你认为如果我使用这种方法而不是我自己的回调它会不再崩溃吗?
如果您需要更多澄清或不需要,请告诉我。
这是代码的主旨: 公共接口类ISmileServiceEvents { public://必需的方法 虚拟void UpdateUI(bool isValid)abstract; };
// In main XAML.cpp which inherits from an ISmileServiceEvents
void buttonClick(...){
_myUser->LoginAndGetAssets(txtEmail->Text, txtPass->Password);
}
void UpdateUI(String^ data) // implements ISmileServiceEvents
{
// This is where I would render my assets if I could.
// Cannot legally do much here. Always crashes.
// Follow the rest of the code to get here.
}
// In MyUser.cpp
void LoginAndGetAssets(String^ email, String^ password){
Uri^ uri = ref new URI(MY_SERVER + "login.json");
String^ inJSON = "some json input data here"; // serialized email and password with other data
// make the HTTP request to login, then notify XAML that it has data to render.
_myService->HTTPPostAsync(uri, json).then([](String^ outputJson){
String^ assets = MyParser::Parse(outputJSON);
// The Login has returned and we have our json output data
if(_delegate)
{
_delegate->UpdateUI(assets);
}
});
}
// In MyService.cpp
task<String^> MyService::HTTPPostAsync(Uri^ uri, String^ json)
{
return _httpRequest.PostAsync(uri,
json->Data(),
_cancellationTokenSource.get_token()).then([this](task<std::wstring> response)
{
try
{
if(_httpRequest.GetStatusCode() != 200) SM_LOG_WARNING("Status code=", _httpRequest.GetStatusCode());
String^ j = ref new String(response.get().c_str());
return j;
}
catch (Exception^ ex) .......;
return ref new String(L"");
}, task_continuation_context::use_current());
}
编辑:BTW,我在更新UI时得到的错误是: “将无效参数传递给认为无效参数致命的函数。” 在这种情况下,我只是试图在我的回调中执行
txtBox->Text = data;
答案 0 :(得分:0)
您似乎正在从错误的上下文更新UI线程。您可以使用task_continuation_context::use_arbitrary()
来更新UI。请参阅this document中的“控制执行线程”示例(编组的讨论位于底部)。
答案 1 :(得分:0)
因此,事实证明,当你有一个延续时,如果你没有在lambda函数之后指定一个上下文,那么它默认为use_arbitrary()。这与我在MS视频中学到的内容相矛盾。
然而,通过将use_currrent()添加到与GUI有关的所有.then块,我的错误消失了,一切都能够正确呈现。
我的GUI调用生成一些任务的服务,然后调用也执行异步操作的HTTP类。回到HTTP类,我使用use_arbitrary(),以便它可以在辅助线程上运行。这很好用。只要确保在与GUI有关的任何事情上使用use_current()。
现在您有了我的答案,如果查看原始代码,您会看到它已经包含use_current()。这是事实,但为了简化示例,我遗漏了一个包装函数。这是我需要添加use_current()的地方。