Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Qt在主线程上运行lambda_C++_Qt - Fatal编程技术网

C++ Qt在主线程上运行lambda

C++ Qt在主线程上运行lambda,c++,qt,C++,Qt,在我的应用程序中,我有一个工作线程在文件列表中迭代,我试图更新GUI表视图,以指示当前文件是什么。在我的工作线程中,我在启动新文件时有以下行: emit runOnGui([this,row](){ui.tblFiles->selectRow(row);}); 其中runOnGui是一个信号,通过以下方式处理: connect(this, &MainWindow::runOnGui, [this](function<void()> action){ actio

在我的应用程序中,我有一个工作线程在文件列表中迭代,我试图更新GUI表视图,以指示当前文件是什么。在我的工作线程中,我在启动新文件时有以下行:

emit runOnGui([this,row](){ui.tblFiles->selectRow(row);});
其中runOnGui是一个信号,通过以下方式处理:

connect(this, &MainWindow::runOnGui, [this](function<void()> action){
    action();
    });
connect(this,&main窗口::runOnGui,[this](函数操作){
动作();
});
我的理解是action()现在应该在UI线程上运行,但有时,并非总是这样,这对我来说是错误的。回溯看起来像:

#0  0x00007ffff537c28a in ?? () from /usr/lib/libQt5Core.so.5
#1  0x00007ffff537cf23 in ?? () from /usr/lib/libQt5Core.so.5
#2  0x00007ffff537d047 in ?? () from /usr/lib/libQt5Core.so.5
#3  0x00007ffff5376943 in QItemSelection::merge(QItemSelection const&, QFlags<QItemSelectionModel::SelectionFlag>) () from /usr/lib/libQt5Core.so.5
#4  0x00007ffff5379e43 in QItemSelectionModel::select(QItemSelection const&, QFlags<QItemSelectionModel::SelectionFlag>) () from /usr/lib/libQt5Core.so.5
#5  0x00007ffff6d97511 in ?? () from /usr/lib/libQt5Widgets.so.5
#6  0x0000000000465193 in MainWindow::<lambda()>::operator()(void) const (__closure=0x7fffda262710) at <...>/MainWindow.cpp:248
#7  0x00000000004682c8 in std::_Function_handler<void(), MainWindow::pushFiles()::<lambda()> >::_M_invoke(const std::_Any_data &) (__functor=...) at /usr/include/c++/6.2.1/functional:1740
#8  0x0000000000472722 in std::function<void ()>::operator()() const (this=0x7fffda262710) at /usr/include/c++/6.2.1/functional:2136
#9  0x0000000000463798 in MainWindow::MainWindow(QWidget*)::{lambda(std::function<void ()>)#1}::operator()(std::function<void ()>) const () at <...>/MainWindow.cpp:34
#10 0x0000000000469a32 in QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<std::function<void()> >, void, MainWindow::MainWindow(QWidget*)::<lambda(std::function<void()>)> >::call(MainWindow::<lambda(std::function<void()>)> &, void **) (f=..., arg=0x7fffda2628e0) at /usr/include/qt/QtCore/qobjectdefs_impl.h:501
#11 0x000000000046977b in QtPrivate::Functor<MainWindow::MainWindow(QWidget*)::<lambda(std::function<void()>)>, 1>::call<QtPrivate::List<std::function<void()> >, void>(MainWindow::<lambda(std::function<void()>)> &, void *, void **) (f=..., arg=0x7fffda2628e0) at /usr/include/qt/QtCore/qobjectdefs_impl.h:558
#12 0x0000000000468d8c in QtPrivate::QFunctorSlotObject<MainWindow::MainWindow(QWidget*)::<lambda(std::function<void()>)>, 1, QtPrivate::List<std::function<void()> >, void>::impl(int, QtPrivate::QSlotObjectBase *, QObject *, void **, bool *) (which=1, this_=0x7cc630, r=0x7fffffffe500, a=0x7fffda2628e0, ret=0x0) at /usr/include/qt/QtCore/qobject_impl.h:198
#13 0x00007ffff53ed85e in QMetaObject::activate(QObject*, int, int, void**) () from /usr/lib/libQt5Core.so.5
#14 0x000000000047a669 in MainWindow::runOnGui(std::function<void ()>) (this=0x7fffffffe500, _t1=...) at <...>/moc_MainWindow.cpp:128
#15 0x0000000000465617 in MainWindow::pushFiles (this=0x7fffffffe500) at <...>/MainWindow.cpp:248
#16 0x0000000000476d14 in std::__invoke_impl<void, void (MainWindow::* const&)(), MainWindow*>(std::__invoke_memfun_deref, void (MainWindow::* const&)(), MainWindow*&&) ( __f=@0xa35080: (void (MainWindow::*)(MainWindow * const)) 0x4651ea <MainWindow::pushFiles()>, __t=<unknown type in <...>/simtool, CU 0x16a5cd, DIE 0x1cbd99>) at /usr/include/c++/6.2.1/functional:235
#17 0x0000000000476ca1 in std::__invoke<void (MainWindow::* const&)(), MainWindow*>(void (MainWindow::* const&)(), MainWindow*&&) ( __fn=@0xa35080: (void (MainWindow::*)(MainWindow * const)) 0x4651ea <MainWindow::pushFiles()>, __args#0=<unknown type in <...>/simtool, CU 0x16a5cd, DIE 0x1cbd99>) at /usr/include/c++/6.2.1/functional:260
#18 0x0000000000476c52 in std::_Mem_fn_base<void (MainWindow::*)(), true>::operator()<MainWindow*>(MainWindow*&&) const (this=0xa35080, __args#0=<unknown type in <...>/simtool, CU 0x16a5cd, DIE 0x1cbd99>) at /usr/include/c++/6.2.1/functional:613
#19 0x0000000000476c1d in std::_Bind_simple<std::_Mem_fn<void (MainWindow::*)()> (MainWindow*)>::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0xa35078) at /usr/include/c++/6.2.1/functional:1400
#20 0x0000000000476b37 in std::_Bind_simple<std::_Mem_fn<void (MainWindow::*)()> (MainWindow*)>::operator()() ( this=0xa35078) at /usr/include/c++/6.2.1/functional:1389
#21 0x0000000000476ad6 in std::thread::_State_impl<std::_Bind_simple<std::_Mem_fn<void (MainWindow::*)()> (MainWindow*)> >::_M_run() (this=0xa35070) at /usr/include/c++/6.2.1/thread:196
#22 0x00007ffff4e6e31f in std::execute_native_thread_routine (__p=0xa35070) at /build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:83
#23 0x00007ffff743f454 in start_thread () from /usr/lib/libpthread.so.0
#24 0x00007ffff45e27df in clone () from /usr/lib/libc.so.6
#0 0x00007FF537C28A英寸??()来自/usr/lib/libQt5Core.so.5
#1 0x00007FF537CF23英寸??()来自/usr/lib/libQt5Core.so.5
#2 0x00007FF537D047英寸??()来自/usr/lib/libQt5Core.so.5
#来自/usr/lib/libQt5Core.so.5的QItemSelection::merge(QItemSelection const&,QFlags)()中的3 0x00007ffff5376943
#4 0x00007FF5379E43在/usr/lib/libQt5Core.so.5中的QItemSelectionModel::select(QItemSelection const&,QFlags)()中
#5 0x00007ffff6d97511英寸??()来自/usr/lib/libQt5Widgets.so.5
#主窗口中的6 0x0000000000465193:::运算符()(无效)常量(_closure=0x7fffda262710)位于/MainWindow.cpp:248
#在/usr/include/c++/6.2.1/functional:1740中,标准:处理程序:中的7 0x00000000004682c8
#在/usr/include/c++/6.2.1/functional:2136的std::function::operator()()const(this=0x7fffda262710)中的8 0x000000000047222
#MainWindow::MainWindow(QWidget*):{lambda(std::function)#1}::operator()(std::function)const()位于/MainWindow.cpp:34
#位于/usr/include/qt/QtCore/qobjectdefs_impl.h:501的QtPrivate::FunctorCall::call(主窗口::&,void**)(f=…,arg=0x7fffda2628e0)中的10 0x0000000000469a32
#11在/usr/include/qt/QtCore/qobjectdefs_impl.h:558处的QtPrivate::Functor::call(主窗口::&,void*,void**)(f=…,arg=0x7fffda2628e0)中的0x00000000004697b
#在/usr/include/qt/QtCore/QObject\u impl.h:198处的QtPrivate::QFunctorSlotObject::impl(int,QtPrivate::QSlotObjectBase*,QObject*,void**,bool*)(其中=1,this=0x7cc630,r=0x7fffffffffe500,a=0x7fffda2628e0,ret=0x0)中的12 0x0000000000468d8c
#13/usr/lib/libQt5Core.so.5中QMetaObject::activate(QObject*,int,int,void**)中的0x00007ffff53ed85e
#14 0x000000000047a669在/moc_MainWindow.cpp:128处的主窗口::runngui(std::函数)(this=0x7fffffffe500,_t1=…)中
#在/MainWindow.cpp:248的MainWindow::pushFiles(this=0x7fffffffe500)中的15 0x0000000000465617
#16 0x0000000000476d14标准格式::uu invoke_impl(标准::u invoke_memfun_deref,void(主窗口::*const&(),主窗口*&&)(uu f=@0xa35080:(void(主窗口::*)(主窗口*const))0x4651ea,u t=)at/usr/include/c++/6.2.1/函数:235
#17 0x0000000000476ca1在std::u调用(void(MainWindow::*const&(),MainWindow*&&)(uu-fn=@0xa35080:(void(MainWindow::*)(MainWindow*const))0x4651ea,u-args#0=)at/usr/include/c++/6.2.1/函数:260
#标准中的18 0x0000000000476c52::_Mem_fn_base::operator()(MainWindow*&&)const(this=0xa35080,uu args#0=)at/usr/include/c++/6.2.1/functional:613
#标准中的19 0x0000000000476c1d::_Bind_simple::_M_invoke(标准::_Index_tuple)(this=0xa35078)位于/usr/include/c++/6.2.1/functional:1400
#20 0x0000000000476b37在/usr/include/c++/6.2.1/functional:1389的std:_Bind_simple::operator()()(this=0xa35078)中
#std::thread::_State_impl::_M_run()(this=0xa35070)at/usr/include/c++/6.2.1/thread:196中的21 0x0000000000476ad6
#22 std::在/build/gcc/src/gcc/libstdc++-v3/src/c++11/thread.cc:83处执行本机线程例程(p=0xa35070)中的0x00007ffff4e6e31f
#23 0x00007FF743F454位于/usr/lib/libpthread.so.0的start_线程()中
#/usr/lib/libc.so.6的克隆()中的24 0x00007ffff45e27df
知道为什么会发生这种故障吗

杂项信息:

  • Qt 5.7
  • ArchLinux4.7.4
  • 通用条款6.2.1

在信号/插槽连接中跨越线程边界的自动操作需要一个接收器对象,以便发出代码可以检查当前线程是否与接收器的线程相同或不同

您可以尝试使用引用对象作为第三个参数的连接变量,或者使用
QMetaObject::invokeMethod()
调用插槽,并明确声明
Qt::QueuedConnection
作为连接类型

例如


我不确定您是否可以使用lambdas或
std::function
作为信号的参数。我想这是你的问题。这看起来也是一个奇怪的设计。但是qt会抱怨吗?我还遇到过其他情况,qt在运行时抱怨我必须使用qRegisterMetaType的未注册类型。我有点认为这种情况也可能发生,但它从未抱怨过。老实说,我没有任何线索。本文档未将其限制为任何类型,因此它可以正常工作。但看起来还是有点奇怪。可能不使用闭包类型,而是将其直接强制转换为
std::function
对象,并将其作为参数。虽然我假设这会发生,因为std::函数可能在信号签名中。实际上,你基本上是对的,但因为我使用的connect函数签名,它正在打印警告。以凯文的回答为出发点得到了运行时信息I。@Hayt函子在这里是信号的“参数”吗?Qt 5支持连接到functor。通过此方法设置连接会突出显示Qt不自动知道如何传递std::function对象。因此,我正在创建一个GuiAction包装器,我可以注册到元类型系统中,希望它能够正常工作。
invokeMethod
会产生字符串索引方法查找的开销。它可以工作,但没有必要过早地悲观。@ryan0270对于自动线程交叉连接,信号的参数需要存储在
QVariant
中,因为机制使用内部自定义事件将数据发送到接收对象的线程事件循环。任何自定义类型都需要
QMetaObject::invokeMethod(ui.tblFiles, "selectRow", Qt::QueuedConnection, Q_ARG(int, row));