2014-10-20 4 views
8

Hy से रोका नहीं जा सकता,क्यूटी टाइमर एक और धागा

मैं अपनी पहली क्यूटी कार्यक्रम लिख रहा हूँ और साथ मुसीबतों में अब हो रही:

QObject :: killTimer: टाइमर एक और धागा से रोका नहीं जा सकता

QObject :: startTimer: टाइमर एक और धागा

मेरे प्रोग्राम है जो मैं कर रहा हूँ के लिए एक CANOpen बस के साथ संचार करेगा से शुरू नहीं किया जा सकता Canfestival Stack का उपयोग कर। कैनफ़ोस्ट कॉलबैक विधियों के साथ काम करेगा। संचार में टाइमआउट का पता लगाने के लिए मैंने एक टाइमर फ़ंक्शन सेट किया है (किसी भी तरह वॉचडॉग की तरह)। मेरा टाइमर पैकेज "टीएमआर" मॉड्यूल, "टाइमरफॉरएफडब्ल्यू अपग्रेड" मॉड्यूल और "सिंगल टाइमर" मॉड्यूल से बाहर है। "टीएमआर" मॉड्यूल मूल रूप से सी प्रोग्राम किया गया था, इसलिए स्थैतिक "टाइमरफॉरएफडब्ल्यू अपग्रेड" विधियों को इंटरफ़ेस किया जाएगा। "टीएमआर" मॉड्यूल सी प्रोग्राम किए गए फर्मवेयर अपडेट पैकेज का हिस्सा होगा।

टाइमर निम्नानुसार काम करेगा। संदेश भेजने से पहले मैं TMR_Set विधि को कॉल करूंगा। उसके बाद टीएमआर_आईएस के साथ मेरे निष्क्रिय प्रोग्राम लूप में हम टाइमर अंडरफ्लो की जांच करते हैं। अगर TMR_IsElapsed मैं त्रुटि प्रबंधन करूँगा। जैसा कि आप देखते हैं कि TMR_Set विधि को लगातार कॉल किया जाएगा और QTimer को बार-बार पुनरारंभ करें।

उपर्युक्त त्रुटियां दिखाई दे रही हैं यदि मैं अपना प्रोग्राम शुरू करता हूं। क्या आप मुझे बता सकते हैं कि मेरी अवधारणा काम कर सकती है? यह त्रुटियां क्यों दिखाई देती हैं? क्या मुझे मुख्य धागे में अतिरिक्त धागे (QThread) का उपयोग करना है?

धन्यवाद

मैट

भागो और निष्क्रिय पाश:

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 
    .... 
} 

मॉड्यूल tmr (इंटरफ़ेस सी कार्यक्रम के लिए):

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

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

मॉड्यूल 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; 
    } 
} 

मॉड्यूल 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

आपके पास बहुत ऊपर है। आप 'क्यूटीमर' वर्ग का उपयोग क्यों नहीं करते? –

+0

'isElapsed()' का शरीर इतना गलत है। – UmNyobe

+0

@UmNyobe क्या आप मुझे और जानकारी दे सकते हैं? शरीर में क्या गलत है? धन्यवाद – Matt

उत्तर

6

इस उद्देश्य के लिए उपयोग QTimer और शुरू करने और टाइमर/s से अलग धागे को रोकने के उद्देश्य के लिए SIGNALS और SLOT का इस्तेमाल करते हैं । आप सिग्नल को किसी थ्रेड से उत्सर्जित कर सकते हैं और इसे थ्रेड में पकड़ सकते हैं जिसने टाइमर को इस पर कार्य करने के लिए बनाया है।

चूंकि आप कहते हैं कि आप क्यूटी के लिए नए हैं, तो मेरा सुझाव है कि आप आगे बढ़ने से पहले कुछ ट्यूटोरियल्स के माध्यम से जाएं ताकि आप जान सकें कि क्यूटी को क्या पेशकश करनी है और पहिया को फिर से शुरू करने की कोशिश नहीं करनी है। :)

VoidRealms एक अच्छा प्रारंभिक बिंदु है।

5

आपको यह समस्या है क्योंकि स्थिर सरणी में टाइमर Thread X में बनाए गए हैं, लेकिन Thread Y में शुरू और बंद कर दिया गया। इसकी अनुमति नहीं है, क्योंकि क्यूटी टाइमआउट टाइमर के लिए थ्रेड एफ़िनिटी पर भरोसा करती है।

आप या तो बना सकते हैं, उसी धागे में रुकना शुरू कर सकते हैं या सिग्नल और स्लॉट का उपयोग start और stop टाइमर के लिए संचालन को ट्रिगर करने के लिए कर सकते हैं। क्योंकि आप n QTimer ऑब्जेक्ट संकेत और स्लॉट समाधान थोड़ा समस्याग्रस्त है (संकेत: कैसे आप स्थिति i पर टाइमर शुरू करूँ?)

आप के बजाय कर बना सकते हैं और

में स्थिति tmrnbr पर टाइमर प्रारंभ कर सकते हैं क्या
TimerForFWUpgrade::set(unsigned char tmrnbr, unsigned int time) 
{ 
    singleTimer[tmrnbr] = new SingleTimer(0); 
    singleTimer[tmrnbr]->set(time); 
} 

जो एक ही थ्रेड द्वारा निष्पादित किया जाता है।

फ़्यूथरमोर, आपको SingleTimer कक्षा की आवश्यकता नहीं है। आप Qt5 उपयोग कर रहे हैं, और आप पहले से ही सब आप अपने निपटान में की जरूरत है:

  • SingleTimer::isElapsed वास्तव में QTimer::remainingTime() == 0 है;
  • SingleTimer::setQTimer::setSingleShot(true); QTimer::start(time);
  • SingleTimer::slot_setElapsed बेकार हो जाता है
  • इस प्रकार SingleTimer::SingleTimer बेकार हो जाता है और आप एक SingleTimer वर्ग अब
0

मैं त्रुटियों दूर मेरी घड़ी अवधारणा को बदलने के बाद मिला है की आवश्यकता नहीं है वास्तव में है। मैं अब अपने सिंगल टाइमर मॉड्यूल का उपयोग नहीं करूँगा। क्यूटीमर से पहले मैं टाइमआउट नहीं करूंगा और शायद इसके कारण मैं समस्याओं में भाग लेता हूं। अब मेरे पास एक चक्रीय QTimer है जो स्लॉट फ़ंक्शन में हर 100ms से बाहर निकलता है, फिर मैं घटनाओं की गणना करूंगा। मेरे कामकाजी कोड के नीचे:

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; 
      } 
     } 
    } 
} 
संबंधित मुद्दे