netease-im / NIM_Duilib_Framework

网易云信Windows应用开发框架。
MIT License
2.06k stars 830 forks source link

销毁登录窗口的时候,报错Debug Assertion Failed! #99

Closed zouhuigang closed 5 years ago

zouhuigang commented 5 years ago

问题现象

测试登录,然后到主界面的时候,报错:

File: d:\software\vs2013\vc\include\vector Line: 101

Expression: vector iterator not incrementable

For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

loginForm.h继承了:

  class LoginForm : public nim_comp::WindowEx

回调:

  xxx::OnHideWindow cb_hide = [this]{
    QLOG_APP(L"-----login hidewindow calback-----");
    this->ShowWindow(false, false);
};

xxx::OnDestroyWindow cb_destroy = [this]{
    ::DestroyWindow(this->GetHWND());
};
xxx:OnShowMainWindow cb_show_main = [this]{
    QLOG_APP(L"-----login showwindow calback-----");
    nim_comp::WindowsManager::SingletonShow<BasicForm>(BasicForm::kClassName);
};

重现步骤

1.

           xxx::GetInstance()->InvokeHideWindow();
    xxx:GetInstance()->InvokeLoginError(200);

    xxx::GetInstance()->InvokeShowMainForm();
    xxx::GetInstance()->InvokeDestroyWindow();

2.当程序回调到InvokeDestroyWindow这个函数的时候,里面的::DestroyWindow(this->GetHWND());这行代码会报错。

zouhuigang commented 5 years ago

用了Post2UI(nbase::Bind(&functionxxx));就好了,还不是很懂其中的原理,难道跟线程有关?主线程不是ui线程嘛~~

nmgwddj commented 5 years ago

底层回调上来的线程是 SDK 的线程,在回调中直接操作 UI 是会有问题的。NIM SDK 较早版本时回调的线程没有做处理,请关注 NIM SDK C++ 封装层代码的变动,允许上层将回调投递到任意其他线程中来使用:C++封装层设置回调接口,一般在初始化时就通知 SDK 将所有回调线程全部投递到 UI(主线程)应用层设置回调示例

zouhuigang commented 5 years ago

感谢指导,试了下,真的可以。

点击登录的时候,使用:

 void TestForm::UILogoutCallback(){
     nim_ui::LoginManager::GetInstance()->InvokeHideWindow();
     nim_ui::LoginManager::GetInstance()->InvokeLoginError(200);

     nim_ui::LoginManager::GetInstance()->InvokeShowMainForm();
     nim_ui::LoginManager::GetInstance()->InvokeDestroyWindow();

}
bool TestForm::OnClicked(ui::EventArgs* msg)
{
    std::wstring name = msg->pSender->GetName();
    if (name == L"btn_login")
    {
            auto cb = std::bind(UILogoutCallback);
            nim::Client::Login("api_key","user_name", "user_passwd", cb);
       }
}