WApplication::bind() 与 Wt::WServer::post 结合使用
WApplication::bind() usage in combination with Wt::WServer::post
我想绑定一个回调,它将被Wt事件循环外的线程调用。
所以很明显我想使用 Wt::WServer::post,但我不知道应该如何使用 WApplication::bind,因为它是一个非静态函数。
第一次尝试是这样的:
auto loaded_callback = [](const decltype(Wt::WApplication::sessionId) &session){
Wt::WServer::post(session,
Wt::WApplication::bind(&table_model::member_func),)
};
这当然行不通,因为 bind
是非静态的。然而我的下一次尝试
auto object_protect_bind =
Wt::WApplication::instance()->bind(&order_aggregate_table_model::load_future_in_map);
因一大堆编译器错误而失败
Error 153 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int \boost\function\function_template.hpp 922 1 MDDB_Web
Error 156 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int \boost\function\function_template.hpp 926 1 MDDB_Web
Error 160 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int \boost\function\function_template.hpp 927 1 MDDB_Web
Error 150 error C2903: 'apply' : symbol is neither a class template nor a function template \boost\function\function_template.hpp 922 1 MDDB_Web
Error 162 error C2825: 'manager_type': must be a class or namespace when followed by '::' \boost\function\function_template.hpp 934 1 MDDB_Web
Error 154 error C2653: 'handler_type' : is not a class or namespace name \boost\function\function_template.hpp 926 1 MDDB_Web
Error 158 error C2653: 'handler_type' : is not a class or namespace name \boost\function\function_template.hpp 927 1 MDDB_Web
Error 164 error C2275: 'manager_type' : illegal use of this type as an expression \boost\function\function_template.hpp 934 1 MDDB_Web
Error 165 error C2146: syntax error : missing '}' before identifier 'manage' \boost\function\function_template.hpp 934 1 MDDB_Web
Error 159 error C2146: syntax error : missing ';' before identifier 'manager_type' \boost\function\function_template.hpp 927 1 MDDB_Web
Error 155 error C2146: syntax error : missing ';' before identifier 'invoker_type' \boost\function\function_template.hpp 926 1 MDDB_Web
Error 152 error C2143: syntax error : missing ';' before '<' \boost\function\function_template.hpp 922 1 MDDB_Web
Error 163 error C2039: 'manage' : is not a member of '`global namespace'' \boost\function\function_template.hpp 934 1 MDDB_Web
Error 151 error C2039: 'apply' : is not a member of 'boost::detail::function::get_invoker0' \boost\function\function_template.hpp 922 1 MDDB_Web
Error 166 error C1903: unable to recover from previous error(s); stopping compilation \boost\function\function_template.hpp 934 1 MDDB_Web
虽然我想到的整体解决方案是:
auto sessionId = Wt::WApplication::instance()->sessionId();
auto server_ptr = Wt::WServer::instance();
auto object_protect_bind = Wt::WApplication::instance()->bind(&order_aggregate_table_model::load_future_in_map);
auto inner_bind = std::bind(object_protect_bind, this);
auto loaded_callback = []
(Wt::WServer* server,
const std::string &session,
boost::function<void()> widget_bind)
-> void {
server->post(session, widget_bind, boost::function<void()>());
};
this->data_future =
std::async(std::launch::async,
table_model::load_quiet_a_bunch_of_data,
query, database, std::bind(loaded_callback, server_ptr, sessionId, inner_bind));
Wt::WTimer::singleShot(20 * 1000, this, &table_model::load_future_in_map);
有什么建议吗?
感谢 Koen Deforche in the official forum,问题是:
Wt::WApplication::bind
应该采用已经绑定的方法,而不是方法本身。
在使用 lambdas 时还有一个令人惊讶的(至少对我来说)模板细节,所以为了举例,我的数据加载线程使用的回调解决方案是:
static std::map<decltype(views::measurements_grouped_by_orders::order_number),
order_value>
order_aggregate_table_model::async_load_order_values(
const odb::query<views::measurements_grouped_by_orders> &query,
std::shared_ptr<odb::database> mddb,
std::function<void(void)> callback) {...
if (callback){ callback(); }
return map;
}
void order_aggregate_table_model::get_data(const odb::query<views::measurements_grouped_by_orders> &query){
auto sessionId = Wt::WApplication::instance()->sessionId();
auto server_ptr = Wt::WServer::instance();
auto object_protect_bind =
Wt::WApplication::instance()->bind(/*Wt::WApplication::bind
handles the case that
the widget might already been destroyed*/
std::bind(&order_aggregate_table_model::load_future_in_map,this));
auto loaded_callback = []
(Wt::WServer* server,
const std::string &session,
std::function<void()> widget_bind)
-> void {
server->post(session, widget_bind, boost::function<void()>());
//Wt::Server::post handles the case when the session is already been destroyed
};
std::function<void()> final_callback = //Because of template quirks had to stick the type
std::bind(loaded_callback, server_ptr, sessionId, object_protect_bind);
this->order_aggregate_map_future =
std::async(std::launch::async,
order_aggregate_table_model::async_load_order_values,
query, this->mddb, final_callback);
Wt::WTimer::singleShot(30 * 1000, this,
&order_aggregate_table_model::load_future_in_map); //For the case that the async loader crashed
}
我想绑定一个回调,它将被Wt事件循环外的线程调用。 所以很明显我想使用 Wt::WServer::post,但我不知道应该如何使用 WApplication::bind,因为它是一个非静态函数。 第一次尝试是这样的:
auto loaded_callback = [](const decltype(Wt::WApplication::sessionId) &session){
Wt::WServer::post(session,
Wt::WApplication::bind(&table_model::member_func),)
};
这当然行不通,因为 bind
是非静态的。然而我的下一次尝试
auto object_protect_bind =
Wt::WApplication::instance()->bind(&order_aggregate_table_model::load_future_in_map);
因一大堆编译器错误而失败
Error 153 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int \boost\function\function_template.hpp 922 1 MDDB_Web Error 156 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int \boost\function\function_template.hpp 926 1 MDDB_Web Error 160 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int \boost\function\function_template.hpp 927 1 MDDB_Web Error 150 error C2903: 'apply' : symbol is neither a class template nor a function template \boost\function\function_template.hpp 922 1 MDDB_Web Error 162 error C2825: 'manager_type': must be a class or namespace when followed by '::' \boost\function\function_template.hpp 934 1 MDDB_Web Error 154 error C2653: 'handler_type' : is not a class or namespace name \boost\function\function_template.hpp 926 1 MDDB_Web Error 158 error C2653: 'handler_type' : is not a class or namespace name \boost\function\function_template.hpp 927 1 MDDB_Web Error 164 error C2275: 'manager_type' : illegal use of this type as an expression \boost\function\function_template.hpp 934 1 MDDB_Web Error 165 error C2146: syntax error : missing '}' before identifier 'manage' \boost\function\function_template.hpp 934 1 MDDB_Web Error 159 error C2146: syntax error : missing ';' before identifier 'manager_type' \boost\function\function_template.hpp 927 1 MDDB_Web Error 155 error C2146: syntax error : missing ';' before identifier 'invoker_type' \boost\function\function_template.hpp 926 1 MDDB_Web Error 152 error C2143: syntax error : missing ';' before '<' \boost\function\function_template.hpp 922 1 MDDB_Web Error 163 error C2039: 'manage' : is not a member of '`global namespace'' \boost\function\function_template.hpp 934 1 MDDB_Web Error 151 error C2039: 'apply' : is not a member of 'boost::detail::function::get_invoker0' \boost\function\function_template.hpp 922 1 MDDB_Web Error 166 error C1903: unable to recover from previous error(s); stopping compilation \boost\function\function_template.hpp 934 1 MDDB_Web
虽然我想到的整体解决方案是:
auto sessionId = Wt::WApplication::instance()->sessionId();
auto server_ptr = Wt::WServer::instance();
auto object_protect_bind = Wt::WApplication::instance()->bind(&order_aggregate_table_model::load_future_in_map);
auto inner_bind = std::bind(object_protect_bind, this);
auto loaded_callback = []
(Wt::WServer* server,
const std::string &session,
boost::function<void()> widget_bind)
-> void {
server->post(session, widget_bind, boost::function<void()>());
};
this->data_future =
std::async(std::launch::async,
table_model::load_quiet_a_bunch_of_data,
query, database, std::bind(loaded_callback, server_ptr, sessionId, inner_bind));
Wt::WTimer::singleShot(20 * 1000, this, &table_model::load_future_in_map);
有什么建议吗?
感谢 Koen Deforche in the official forum,问题是:
Wt::WApplication::bind
应该采用已经绑定的方法,而不是方法本身。
在使用 lambdas 时还有一个令人惊讶的(至少对我来说)模板细节,所以为了举例,我的数据加载线程使用的回调解决方案是:
static std::map<decltype(views::measurements_grouped_by_orders::order_number),
order_value>
order_aggregate_table_model::async_load_order_values(
const odb::query<views::measurements_grouped_by_orders> &query,
std::shared_ptr<odb::database> mddb,
std::function<void(void)> callback) {...
if (callback){ callback(); }
return map;
}
void order_aggregate_table_model::get_data(const odb::query<views::measurements_grouped_by_orders> &query){
auto sessionId = Wt::WApplication::instance()->sessionId();
auto server_ptr = Wt::WServer::instance();
auto object_protect_bind =
Wt::WApplication::instance()->bind(/*Wt::WApplication::bind
handles the case that
the widget might already been destroyed*/
std::bind(&order_aggregate_table_model::load_future_in_map,this));
auto loaded_callback = []
(Wt::WServer* server,
const std::string &session,
std::function<void()> widget_bind)
-> void {
server->post(session, widget_bind, boost::function<void()>());
//Wt::Server::post handles the case when the session is already been destroyed
};
std::function<void()> final_callback = //Because of template quirks had to stick the type
std::bind(loaded_callback, server_ptr, sessionId, object_protect_bind);
this->order_aggregate_map_future =
std::async(std::launch::async,
order_aggregate_table_model::async_load_order_values,
query, this->mddb, final_callback);
Wt::WTimer::singleShot(30 * 1000, this,
&order_aggregate_table_model::load_future_in_map); //For the case that the async loader crashed
}