2009-12-31 40 views
3

我剛學的Qt,有一個非常基本的問題。問題關於Qt插槽和多個呼叫

如果在一個插槽中有一個(函數作用域)變量,並且插槽被多次調用,每次在最後一次調用返回之前(這甚至可能?),每次都會覆蓋變量嗎?從某種意義上說,如果在上一次運行返回之前調用槽,是不是會導致錯誤?

謝謝。

回答

1

如果你真的使用函數範圍的變量,那麼它不應該的問題。例如:

class WheelSpinner : public QThread 
{ 
Q_OBJECT; 
public: 
    WheelSpinner(QObject* receiver, const char* slot) 
    { 
     connect(this, SIGNAL(valueChanged(int)), receiver, slot, 
       Qt::DirectConnect); 
    } 

    void run() 
    { 
     for (int i = 0; i < 100000; ++i) 
     { 
      emit (valueChanged(i)); 
     } 
    } 

public signals: 
    void valueChanged(int value); 
}; 

class ProgressTracker : public QObject 
{ 
Q_OBJECT; 
public: 
    ProgressTracker() { } 

public slots: 
    void updateProgress(int value) 
    { 
     // While in this function, "value" will always be the proper 
     // value corresponding to the signal that was emitted. 
     if (value == 100000) 
     { 
      // This will cause us to quit when the *first thread* that 
      // emits valueChanged with the value of 100000 gets to this point. 
      // Of course, other threads may get to this point also before the 
      // program manages to quit. 
      QApplication::quit(); 
     } 
    } 
}; 

int main(int argc, char **argv) 
{ 
    QApplication app(argc, argv); 
    ProgressTracker tracker; 
    WheelSpinner spinner1(&tracker, SLOT(updateProgress(int ))); 
    WheelSpinner spinner2(&tracker, SLOT(updateProgress(int ))); 
    WheelSpinner spinner3(&tracker, SLOT(updateProgress(int ))); 

    spinner1.run(); 
    spinner2.run(); 
    spinner3.run(); 

    return (app.exec()); 
} 
+0

因此,在這種情況下,您是說如果同一WheelSpinner對象(稱爲spinner2)爲我調用updateProgress,並且第i-1次調用尚未完成,它仍然會正常運行? – 2009-12-31 19:19:14

+1

@ trex279:首先,通過直接連接,如果spinner2爲我調用updateProgress,它將不會繼續,直到updateProgress函數完成。這部分是連續的。但是,如果spinner1爲i + 1運行,而spinner2仍爲i運行相同的函數,則兩者都將正確執行。 – 2009-12-31 23:21:19

2

是,如果調用從不同的線程進行的,而且您是直接連接。

如果您使用的隊列連接,然後插槽通話將被進行接二連三的事件循環這是您的接收對象所屬的線程上運行。 (編輯感謝Idan K評論)。

結帳Signal and slots的排隊連接或QMutexLocker解決您的問題。

+1

我相信排隊的連接的事件循環QObject的連接來運行。例如,如果你在QThread :: run()中創建一個QObject,它的插槽將在QThread的上下文中處理。 – 2009-12-31 10:05:32

+0

這是對的!謝謝! – fulmicoton 2009-12-31 10:13:37

+0

我不同意,但可能沒有足夠的信息來說明。如果它是一個* function-scope *變量,即使在並行運行的不同線程中,也不應該覆蓋它。在這種情況下,它應該可以正常工作。但是,如果它是一個函數範圍引用或指針變量,則源數據可能已更改,這可能會導致問題。 – 2009-12-31 14:41:47

1

只要功能是reentrant是沒有問題的。

+2

一個重要的注意事項是QObject :: sender()是不可重入的。 – Macke 2010-10-27 14:39:00