2015-04-03 30 views
1

我需要從後臺線程跟蹤我的計算進度。Qt:從後臺線程發出信號安全嗎?

我做這種方式:(從官方文檔拍攝)

void MainWindow::startCalculation() 
{ 

//Progress bar 

ui->cmdLogX->setText(tr("Расчёт...")); 
ui->cmdLogX->setEnabled(false); 


//Create a new Thread 


Worker *worker = new Worker(nullptr, 0.0, 100, 0.1); 
worker->moveToThread(&background); 
connect(&background, &QThread::finished, worker, &QObject::deleteLater); 
connect(this, &MainWindow::runCalculation, worker, &Worker::run); 
connect(worker, &Worker::calculated, this, &MainWindow::plotComputedData); 
connect(worker, &Worker::reportProgress, 
     [this] (int x) { 
    bar->setValue(x);}); 

background.start(QThread::HighPriority); 
emit runCalculation(); 

}

這裏是Worker::run()

void Worker::run() 
{ 
if (_data.size() > 0) 
    _data.clear(); 
int i = 0; 
for (double x = _min; x < _max; x += _step, ++i) 
{ 
    _data.push_back(QPointF(x, getY(x))); 
    //emit reportProgress(i); 
    QThread::msleep(10); 
} 
emit calculated(_data); 
} 

如果我發出reportProgress(I),與應用程序崩潰段錯誤(在不同的功能中,最後一次是QAnimationTimer :: updateAnimationsTime。

MWE:https://www.dropbox.com/s/thgxwc98fevi6v3/qwt-test2.tar.bz2?dl=0

編輯:BT:

(gdb) bt 
#0 0x0000000100caca62 in QAnimationTimer::updateAnimationsTime(long long)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#1 0x0000000100cab5f7 in QUnifiedTimer::updateAnimationTimers(long long)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#2 0x0000000100cad9fc in QAnimationDriver::advance()() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#3 0x0000000100f04300 in QObject::event(QEvent*)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#4 0x0000000100061dbb in QApplicationPrivate::notify_helper(QObject*, QEvent*)() from /Users/pasha/Qt/5.4/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets 
#5 0x0000000100065110 in QApplication::notify(QObject*, QEvent*)() from /Users/pasha/Qt/5.4/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets 
#6 0x0000000100ed8fb3 in QCoreApplication::notifyInternal(QObject*, QEvent*)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#7 0x0000000100f2d3f6 in QTimerInfoList::activateTimers()() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#8 0x0000000105799d12 in QCocoaEventDispatcherPrivate::activateTimersSourceCallback(void*)() from /Users/pasha/Qt/5.4/clang_64/plugins/platforms/libqcocoa.dylib 
#9 0x00007fff88cb2681 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__() from /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 
#10 0x00007fff88ca48dc in __CFRunLoopDoSources0() from /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 
#11 0x00007fff88ca3e3f in __CFRunLoopRun() from /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 
#12 0x00007fff88ca3858 in CFRunLoopRunSpecific() from /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 
#13 0x00007fff8b9daaef in RunCurrentEventLoopInMode() from /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 
#14 0x00007fff8b9da86a in ReceiveNextEventCommon() from /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 
#15 0x00007fff8b9da6ab in _BlockUntilNextEventMatchingListInModeWithFilter() from /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 
#16 0x00007fff91beff81 in _DPSNextEvent() from /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 
#17 0x00007fff91bef730 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]() from /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 
#18 0x00007fff91be3593 in -[NSApplication run]() from /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 
#19 0x000000010579a92d in QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)() from /Users/pasha/Qt/5.4/clang_64/plugins/platforms/libqcocoa.dylib 
#20 0x0000000100ed65ad in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#21 0x0000000100ed958a in QCoreApplication::exec()() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#22 0x0000000100003c69 in main (argc=1, argv=0x7fff5fbffa78) at ../qwt-test2/main.cpp:12 
(gdb) 
#0 0x0000000100caca62 in QAnimationTimer::updateAnimationsTime(long long)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#1 0x0000000100cab5f7 in QUnifiedTimer::updateAnimationTimers(long long)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#2 0x0000000100cad9fc in QAnimationDriver::advance()() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#3 0x0000000100f04300 in QObject::event(QEvent*)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#4 0x0000000100061dbb in QApplicationPrivate::notify_helper(QObject*, QEvent*)() from /Users/pasha/Qt/5.4/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets 
#5 0x0000000100065110 in QApplication::notify(QObject*, QEvent*)() from /Users/pasha/Qt/5.4/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets 
#6 0x0000000100ed8fb3 in QCoreApplication::notifyInternal(QObject*, QEvent*)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#7 0x0000000100f2d3f6 in QTimerInfoList::activateTimers()() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#8 0x0000000105799d12 in QCocoaEventDispatcherPrivate::activateTimersSourceCallback(void*)() from /Users/pasha/Qt/5.4/clang_64/plugins/platforms/libqcocoa.dylib 
#9 0x00007fff88cb2681 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__() from /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 
#10 0x00007fff88ca48dc in __CFRunLoopDoSources0() from /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 
#11 0x00007fff88ca3e3f in __CFRunLoopRun() from /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 
#12 0x00007fff88ca3858 in CFRunLoopRunSpecific() from /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation 
#13 0x00007fff8b9daaef in RunCurrentEventLoopInMode() from /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 
#14 0x00007fff8b9da86a in ReceiveNextEventCommon() from /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 
#15 0x00007fff8b9da6ab in _BlockUntilNextEventMatchingListInModeWithFilter() from /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/HIToolbox 
#16 0x00007fff91beff81 in _DPSNextEvent() from /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 
#17 0x00007fff91bef730 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]() from /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 
#18 0x00007fff91be3593 in -[NSApplication run]() from /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit 
#19 0x000000010579a92d in QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)() from /Users/pasha/Qt/5.4/clang_64/plugins/platforms/libqcocoa.dylib 
#20 0x0000000100ed65ad in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#21 0x0000000100ed958a in QCoreApplication::exec()() from /Users/pasha/Qt/5.4/clang_64/lib/QtCore.framework/Versions/5/QtCore 
#22 0x0000000100003c69 in main (argc=1, argv=0x7fff5fbffa78) at ../qwt-test2/main.cpp:12 

回答

0

您試圖在非主線程,這是在Qt中禁止使用的UI組件。爲了解決這個問題,你可以做這樣的事情:

connect(worker, &Worker::reportProgress, this, 
     [this] (int x) { 
    bar->setValue(x); 
}, Qt::QueuedConnection); 
0

當你這樣做:

connect(worker, &Worker::reportProgress, 
     [this] (int x) { 
     bar->setValue(x);}); 

你沒有信號連接到插槽,而是直接把函數指針。 Qt無法檢查連接是否應排隊,並調用不同線程的線程不安全代碼(GUI)。

而不是使用lambda表達式,在QMainWindow中創建一個用於更新欄的槽,並將線程信號連接到此插槽。然後Qt會正確處理不同線程之間的連接。