首页 > 解决方案 > esp32 arduino 上的分离 std::thread 有时会阻塞,有时不会

问题描述

我有一些代码在带有 arduino 内核的 ESP32 微控制器上运行,在setup()函数中我希望有一些代码threadPressureCalib在自己的线程中独立运行,所以我执行以下操作:

std::unique_ptr<std::thread>  sensorCalib;
void setup()
{
    sensorCalib.reset(new std::thread(threadPressureCalib));
    std::thread*  pc = sensorCalib.get();
    pc->detach();
}


 void loop()
{
...
}

然后,我定义threadPressureCalib()如下:

void threadPressureCalib() 
{
  float pressure=0;
  int count;

  for(timestarted = millis();(millis()-timestarted) < 10000;)
  { // THIS ONE BLOCKS SETUP() AND LOOP() CODE EXECUTION

      Serial.println("Doing things");

  }
  Serial.println("Doing other things");
  for (count=1; count<= 5;count++)
  { //THIS ONE DOES NOT BLOCK SETUP() and LOOP()
    float temp;
    while(!timer2.Delay(2000)); //Not sure if this is blocking anything
    do{
      temp = adc_pressure();
    }while(temp>104.0 || temp<70.0); //Catch errors 
    pressure += temp;

  }
  changeSetting(pressure/5.0);
  return;
  
}

问题:在第一个 for 循环期间,setup()函数的执行被停止(以及loop()

在第二个 for 循环期间,没有任何内容被停止,其余代码并行运行(如预期的那样)

为什么这段代码的前半部分会阻塞,而后半部分不会?

抱歉,如果问题含糊不清或问得不恰当,我的第一个问题就在这里。

注释中每个请求的 timer2 解释:

timer2 是一个自定义计时器类,timer2.Delay(TIMEOUT)它存储第一次调用的时间戳,并false在每次后续调用时返回,直到当前时间 = TIMEOUT,然后它返回true并自行重置

NonBlockDelay timer2;

 //time delay function (time in seconds to delay)
// Set iTimeout to current millis plus milliseconds to wait for  
/** 
 * Called with milliseconds to delay. 
 * Return true if timer expired 
 *  
 */  
//Borrowed from someone on StackOverflow... 

bool NonBlockDelay::Delay (unsigned long t)  
{  
  if(TimingActive)  
  {  
    if((millis() >iTimeout)){  
      TimingActive = 0;  
      return(1);  
    }  
    return(0);  
  }  
  iTimeout = millis() + t;  
  TimingActive = 1;  
  return(0);  
};  

// returns true if timer expired  
bool NonBlockDelay::Timeout (void)  
{  
  if(TimingActive){  
    if((millis() >iTimeout)){  
      TimingActive = 0;  
      iTimeout = 0;  
      return(1);  
    }  
  }  
  return(false);  
} 

// Returns the current timeout value in milliseconds 
unsigned long NonBlockDelay::Time(void)  
 {  
   return iTimeout;  
 }  

标签: c++c++11esp32

解决方案


这里没有足够的信息告诉你答案,但似乎你不知道自己在做什么。

std::unique_ptr<std::thread>  sensorCalib;
void setup(){
      sensorCalib.reset(new std::thread(threadPressureCalib));
      std::thread*  pc = sensorCalib.get();
      pc->detach();
}

因此,您在这里存储了一个新线程,该线程执行threadPressureCalib然后立即将其分离。一旦线程被分离,实例std::thread就不再管理它。那么,std::unique_ptr<std::thread> sensorCalib;如果它实际上什么都不做,那么即使首先拥有又有什么意义呢?你是否意识到join如果你想等到它完成,通常你需要线程?是不是你只是启动了一堆实例threadPressureCalib——因为你可能没有验证它们是否完成了执行——并且它们相互干扰?


推荐阅读