我现在让它工作了。我没有直接调用QtConcurrent::run
,而是使用能够捕获非 Qt 异常的 Qt 包装器。当捕获到异常时,将其推送到主线程到排队连接并重新抛出。
namespace MyConcurrent {
template <class U, class V>
QFuture<U> offload(V func)
{
U (*caller)(V) = offloaded_placeholder<U>;
return QtConcurrent::run(caller, func);
}
template <class U, class V>
U offloaded_placeholder(V func)
{
try
{
return func();
}
catch(Utilities::ExceptionBase& e)
{
qRegisterMetaType<Utilities::ExceptionBase>("Utilities::ExceptionBase");
QMetaObject::invokeMethod(ConcurrencyCommunicator::getInstance(), "onRequestPushExceptionToMainThread", Qt::QueuedConnection, Q_ARG(const Utilities::ExceptionBase&, e));
}
}
}
用法:
QFuture<ret_type> = MyConcurrent::offload<ret_type>(std::bind(&some_func, params));
请注意,这Utilities::ExceptionBase
是一个源自标准异常的类。ConcurrencyCommunicator
是一个简单的类,GUI 有一个指向它的指针。推送的异常在内部重新抛出ConcurrencyCommunicator
,然后被主线程的事件循环捕获。