2014-10-20 18 views
8

Hỷ,giờ Qt không thể dừng lại từ một thread

Tôi đang viết chương trình Qt đầu tiên của tôi và nhận được bây giờ trong những rắc rối với:

QObject :: killTimer: giờ không thể dừng lại từ một thread

QObject :: startTimer: giờ không thể khởi động từ một thread

chương trình của tôi sẽ liên lạc với một chiếc xe buýt CANOpen cho rằng tôi là sử dụng Canfestival Stack. Canfestival sẽ làm việc với các phương thức gọi lại. Để phát hiện thời gian chờ trong giao tiếp, tôi thiết lập một chức năng hẹn giờ (bằng cách nào đó giống như một cơ quan giám sát). Gói bộ hẹn giờ của tôi bao gồm mô-đun "tmr", mô-đun "TimerForFWUpgrade" và mô-đun "SingleTimer". Mô-đun "tmr" ban đầu được lập trình C nên các phương thức "TimerForFWUpgrade" tĩnh sẽ giao tiếp nó. Mô-đun "tmr" sẽ là một phần của gói cập nhật Firmware được lập trình C.

Bộ hẹn giờ sẽ hoạt động như sau. Trước khi một tin nhắn được gửi, tôi sẽ gọi phương thức TMR_Set. Sau đó trong vòng lặp chương trình nhàn rỗi của tôi với TMR_IsElapsed, chúng tôi kiểm tra một bộ đếm thời gian. Nếu TMR_IsElapsed tôi sẽ làm lỗi. Khi bạn thấy phương thức TMR_Set sẽ được gọi liên tục và khởi động lại QTimer một lần nữa và một lần nữa.

Các lỗi được ghi chú ở trên sẽ xuất hiện nếu tôi bắt đầu chương trình của mình. Bạn có thể cho tôi biết liệu khái niệm của tôi có thể hoạt động không? Tại sao lỗi này xuất hiện? Tôi có phải sử dụng các luồng bổ sung (QThread) cho luồng chính không?

Cảm ơn bạn

Matt

Run và vòng lặp Nhàn rỗi:

void run 
{ 
    // start communicate with callbacks where TMR_Set is set continously 
    ... 

    while(TMR_IsElapsed(TMR_NBR_CFU) != 1); 

    // if TMR_IsElapsed check for errorhandling 
    .... 
} 

Mô-đun tmr (giao diện cho chương trình C):

extern "C" 
{ 
void TMR_Set(UINT8 tmrnbr, UINT32 time) 
{ 
    TimerForFWUpgrade::set(tmrnbr, time); 
} 

INT8 TMR_IsElapsed(UINT8 tmrnbr) 
{ 
return TimerForFWUpgrade::isElapsed(tmrnbr); 
} 
} 

Mô-đun TimerForFWUpgrade:

SingleTimer* TimerForFWUpgrade::singleTimer[NR_OF_TIMERS]; 

TimerForFWUpgrade::TimerForFWUpgrade(QObject* parent) 
{ 

    for(unsigned char i = 0; i < NR_OF_TIMERS; i++) 
    { 
     singleTimer[i] = new SingleTimer(parent); 
    } 
} 

//static 
void TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time) 
{ 
    if(tmrnbr < NR_OF_TIMERS) 
    { 
     time *= TimerForFWUpgrade::timeBase; 
     singleTimer[tmrnbr]->set(time); 
    } 

} 


//static 
char TimerForFWUpgrade::isElapsed(unsigned char tmrnbr) 
{ 
    if(true == singleTimer[tmrnbr]->isElapsed()) 
    { 
     return 1; 
    } 
    else 
    { 
     return 0; 
    } 
} 

Mô-đun SingleTimer:

SingleTimer::SingleTimer(QObject* parent) : QObject(parent), 
              pTime(new QTimer(this)), 
              myElapsed(true) 
{ 
    connect(pTime, SIGNAL(timeout()), this, SLOT(slot_setElapsed())); 
    pTime->setTimerType(Qt::PreciseTimer); 
    pTime->setSingleShot(true); 
} 

void SingleTimer::set(unsigned int time) 
{ 
    myElapsed = false; 
    pTime->start(time); 
} 

bool SingleTimer::isElapsed() 
{ 
    QCoreApplication::processEvents(); 
    return myElapsed; 
} 

void SingleTimer::slot_setElapsed() 
{ 
    myElapsed = true; 
} 
+4

Bạn có phí tuyệt vời. Tại sao bạn không sử dụng lớp 'QTimer'? –

+0

phần thân của 'isElapsed()' rất sai. – UmNyobe

+0

@UmNyobe Bạn có thể cho tôi biết thêm thông tin không? Có gì sai trong cơ thể của isElapsed? Cảm ơn – Matt

Trả lời

6

Sử dụng QTimer cho mục đích này và tận dụng SIGNALSSLOT với mục đích khởi động và dừng lại từ chủ đề bộ đếm thời gian/s khác nhau . Bạn có thể phát ra tín hiệu từ bất kỳ chuỗi nào và bắt nó trong chuỗi đã tạo bộ hẹn giờ để hoạt động trên đó.

Vì bạn nói bạn mới làm quen với Qt, tôi khuyên bạn nên thực hiện một số hướng dẫn trước khi tiếp tục để bạn biết những gì Qt cung cấp và không kết thúc cố gắng phát minh lại bánh xe. :)

VoidRealms là điểm khởi đầu tốt.

5

Bạn có vấn đề này vì bộ tính giờ trong mảng tĩnh được tạo trong Thread X, nhưng đã bắt đầu và dừng lại ở Thread Y. Điều này là không được phép, bởi vì Qt dựa vào mối quan hệ luồng với bộ đếm thời gian chờ.

Bạn có thể tạo, bắt đầu dừng trong cùng một chuỗi hoặc sử dụng tín hiệu và vị trí để kích hoạt các hoạt động startstop cho bộ hẹn giờ. Tín hiệu và khe giải pháp là một chút vấn đề Bởi vì bạn có n đối tượng QTimer (Gợi ý: làm thế nào để bạn bắt đầu hẹn giờ ở vị trí i?)

gì bạn có thể làm thay được tạo và khởi tạo bộ đếm thời gian ở vị trí tmrnbr trong

TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time) 
{ 
    singleTimer[tmrnbr] = new SingleTimer(0); 
    singleTimer[tmrnbr]->set(time); 
} 

được thực hiện bởi cùng một chuỗi.

Hơn nữa, bạn không cần lớp học SingleTimer. Bạn đang sử dụng Qt5, và bạn đã có tất cả các bạn cần phải theo ý của bạn:

  • SingleTimer::isElapsed thực sự là QTimer::remainingTime() == 0;
  • SingleTimer::set thực sự là QTimer::setSingleShot(true); QTimer::start(time);
  • SingleTimer::slot_setElapsed trở nên vô dụng
  • Như vậy SingleTimer::SingleTimer trở nên vô dụng và bạn không cần một lớp SingleTimer nữa
0

Tôi đã nhận các lỗi lập tức sau khi thay đổi giờ khái niệm của tôi. Tôi sẽ không còn sử dụng mô-đun SingleTimer của mình nữa. Trước QTimer, tôi sẽ không để thời gian chờ và có lẽ vì điều đó tôi gặp phải vấn đề. Bây giờ tôi có một QTimer tuần hoàn, mỗi lần 100ms trong chức năng khe, tôi sẽ đếm các sự kiện. Bên dưới mã làm việc của tôi:

TimerForFWUpgrade::TimerForFWUpgrade(QObject* parent) : QObject(parent), 
                 pTime(new QTimer(this)) 
{ 
    connect(pTime, SIGNAL(timeout()), this, SLOT(slot_handleTimer())); 
    pTime->setTimerType(Qt::PreciseTimer); 
    pTime->start(100); 
} 

void TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time) 
{ 
    if(tmrnbr < NR_OF_TIMERS) 
    { 
     if(timeBase != 0) 
     { 
      myTimeout[tmrnbr] = time/timeBase; 
     } 
     else 
     { 
      myTimeout[tmrnbr] = 0; 
     } 
     myTimer[tmrnbr] = 0; 
     myElapsed[tmrnbr] = false; 
     myActive[tmrnbr] = true; 
    } 

} 

char TimerForFWUpgrade::isElapsed(unsigned char tmrnbr) 
{ 
    QCoreApplication::processEvents(); 
    if(tmrnbr < NR_OF_TIMERS) 
    { 
     if(true == myElapsed[tmrnbr]) 
     { 
      return 1; 
     } 
     else 
     { 
      return 0; 
     } 
    } 
    else 
    { 
     return 0; // NOK 
    } 
} 

void TimerForFWUpgrade::slot_handleTimer() 
{ 
    for(UINT8 i = 0; i < NR_OF_TIMERS; i++) 
    { 
     if(myActive[i] == true) 
     { 
      myTimer[i]++; 
      if(myTimeout[i] < myTimer[i]) 
      { 
       myTimer[i] = 0; 
       myElapsed[i] = true; 
       myActive[i] = false; 
      } 
     } 
    } 
} 
Các vấn đề liên quan