【发布时间】:2013-01-19 01:36:17
【问题描述】:
有时我需要创建其构造函数需要很长时间才能执行的对象。 这会导致 UI 应用程序出现响应问题。
所以我想知道编写一个设计为异步调用的构造函数是否明智,方法是向它传递一个回调,它会在对象可用时提醒我。
下面是示例代码:
class C
{
public:
// Standard ctor
C()
{
init();
}
// Designed for async ctor
C(std::function<void(void)> callback)
{
init();
callback();
}
private:
void init() // Should be replaced by delegating costructor (not yet supported by my compiler)
{
std::chrono::seconds s(2);
std::this_thread::sleep_for(s);
std::cout << "Object created" << std::endl;
}
};
int main(int argc, char* argv[])
{
auto msgQueue = std::queue<char>();
std::mutex m;
std::condition_variable cv;
auto notified = false;
// Some parallel task
auto f = []()
{
return 42;
};
// Callback to be called when the ctor ends
auto callback = [&m,&cv,¬ified,&msgQueue]()
{
std::cout << "The object you were waiting for is now available" << std::endl;
// Notify that the ctor has ended
std::unique_lock<std::mutex> _(m);
msgQueue.push('x');
notified = true;
cv.notify_one();
};
// Start first task
auto ans = std::async(std::launch::async, f);
// Start second task (ctor)
std::async(std::launch::async, [&callback](){ auto c = C(callback); });
std::cout << "The answer is " << ans.get() << std::endl;
// Mimic typical UI message queue
auto done = false;
while(!done)
{
std::unique_lock<std::mutex> lock(m);
while(!notified)
{
cv.wait(lock);
}
while(!msgQueue.empty())
{
auto msg = msgQueue.front();
msgQueue.pop();
if(msg == 'x')
{
done = true;
}
}
}
std::cout << "Press a key to exit..." << std::endl;
getchar();
return 0;
}
您认为这种设计有什么缺点吗?或者您知道是否有更好的方法吗?
编辑
按照 JoergB 回答的提示,我尝试编写一个工厂,负责以同步或异步方式创建对象:
template <typename T, typename... Args>
class FutureFactory
{
public:
typedef std::unique_ptr<T> pT;
typedef std::future<pT> future_pT;
typedef std::function<void(pT)> callback_pT;
public:
static pT create_sync(Args... params)
{
return pT(new T(params...));
}
static future_pT create_async_byFuture(Args... params)
{
return std::async(std::launch::async, &FutureFactory<T, Args...>::create_sync, params...);
}
static void create_async_byCallback(callback_pT cb, Args... params)
{
std::async(std::launch::async, &FutureFactory<T, Args...>::manage_async_byCallback, cb, params...);
}
private:
FutureFactory(){}
static void manage_async_byCallback(callback_pT cb, Args... params)
{
auto ptr = FutureFactory<T, Args...>::create_sync(params...);
cb(std::move(ptr));
}
};
【问题讨论】:
-
您是否尝试在构造函数中使用 std::async 。我想您可以将异步放入回调并将结果存储为类本身的成员。
-
@thang 我想尝试一下……对我来说,问题是您可能会创建一个对象但尚未准备好使用。在这种情况下,isValid() 方法可能会有所帮助,也许......
-
是的,您可以添加 isValid 或 waitValid 或其他类似的东西。这样,所有内容都被封装到类中......功能相同,只是更整洁一些。
标签: c++ asynchronous c++11 constructor