Conflict of tasks leading to program closing

I have a small project with Arduino that uses FreeRTOS.
In this project I create 2 tasks:
task 1 function is to read temperature, humidity and gas concentration sensor values from DHT11 and MQ2 sensors, then it displays these values on LCD and Serial, and sends data to queue for task 2
task 2 is responsible for reading the values received from the queue and processing, giving warnings if the allowed value is exceeded.
The problem here is:
If there is only task 1, the program runs fine. But if there is task 2, the whole program does not run, only runs through the Setup() function.
I let 2 tasks have the same priority and the same stack value of 400.

I've been trying to fix this problem for over two days now to no result.
Hope to get help from everyone.
Source code :

#include <Arduino_FreeRTOS.h>
#include <queue.h>
#include <task.h>
#include <semphr.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "DHT.h"
const int DHTPIN = 4;
const int DHTTYPE = DHT11;
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 16, 2);
#define ledr 8
#define ledb 7
#define buzzer 2
TaskHandle_t xReadSensor;
TaskHandle_t xHandler;
QueueHandle_t queueGas;
QueueHandle_t queueHum;
QueueHandle_t queueTemp;

void setup() {
  Serial.begin(9600);
  Serial.println("System is setting up!");
  dht.begin();
  lcd.init();
  lcd.backlight();
  lcd.clear();

  xTaskCreate(taskReadSensor, "readss", 400, NULL, 1, &xReadSensor);
  xTaskCreate(taskHandler, "handler", 400, NULL, 1, &xHandler);
  queueGas = xQueueCreate(1, sizeof(int));
  queueHum = xQueueCreate(1, sizeof(int));
  queueTemp = xQueueCreate(1, sizeof(int));

}

void loop() {}

void taskReadSensor() {

  while (1) {
    Serial.println("- - -!- - -");
    int h = dht.readHumidity();
    int t = dht.readTemperature();
    int value = analogRead(A0);
    lcd.setCursor(2, 0);
    lcd.print("Gas value:");
    if (value >= 100) {
      lcd.print(value);
    } else {
      lcd.print(value);
      lcd.print(" ");
    }

    lcd.setCursor(0, 1);
    lcd.print("T:");
    lcd.print(t);
    lcd.setCursor(4, 1);
    lcd.print("*C");

    lcd.setCursor(6, 1);
    lcd.print(" ---");

    lcd.setCursor(11, 1);
    lcd.print("H:");
    lcd.print(h);
    lcd.setCursor(15, 1);
    lcd.print("%");
    delay(1000);

xQueueOverwrite(queueGas, (void*)&value);
xQueueOverwrite(queueTemp , (void*)&t);
xQueueOverwrite(queueHum, (void*)&h);

    Serial.print("Khi gas: ");
    Serial.println(value);
    Serial.print("Nhiet do: ");
    Serial.println(t);
    Serial.print("Do am: ");
    Serial.println(h);

    delay(500);
  }
}

void taskHandler() {
  int gBuffer;
  char gStr[16];
  int hBuffer;
  char hStr[16];
  int tBuffer;
  char tStr[16];
  Serial.println("Handlingggg!");
  while (1) {
    xQueuePeek(queueGas, &gBuffer, ( TickType_t ) 10 );
    xQueuePeek(queueTemp, &tBuffer, ( TickType_t ) 10 );
    xQueuePeek(queueHum, &hBuffer, ( TickType_t ) 10 );
    Serial.println("Peeking data!");
    Serial.println("Gas value: ");
    Serial.println(gBuffer);
    Serial.println("Temp value: ");
    Serial.println(tBuffer);
    Serial.println("Hum value: ");
    Serial.println(hBuffer);

    if (gBuffer >= 300) {
      lcd.clear();
      lcd.setCursor(1, 1);
      lcd.print("Gas detected");
      digitalWrite(ledr, HIGH);
      digitalWrite(ledb, LOW);
      Serial.println("Gas deteced!!!");
      Serial.println("FBI WARING");
    } else {
      digitalWrite(ledr, LOW);
      digitalWrite(ledb, HIGH);
      lcd.clear();
      Serial.println("Normal ^^");
    }

    vTaskDelay(1000 / portTICK_PERIOD_MS);
    taskYIELD();
  }

  
}

An Uno has only enough RAM to run very small sketches. If your sketch uses more then its allocated space, issues.

As a note to you and using freeRTOS, setup the queues BEFORE the tasks start.

Save yourself some space get rid of those print statements / greatly minimize the memory hogging.

And you may need more then 400 stack space address for your code. Use highwatermark freeRTOS macro and print out the memory use for troubleshooting.

log_i( " high watermark %d",  uxTaskGetStackHighWaterMark( NULL ) ); << is the print out task stack use macro.

I like to set the stack use space for a task about 2000 above the max used space during task operations. I let the task run for about 10 minutes before deciding on the stack size.

I just got through setting the task memory use for this app I am currently working on:

/*
  Connect the SD card to the following pins:

  SD Card | ESP32
  D2 -
  D3 SS
  CMD MOSI
  VSS GND
  VDD 3.3V
  CLK SCK
  VSS GND
  D0 MISO
  D1 -
  writeFile(SD, "/hello.txt", "Hello ");
  appendFile(SD, "/hello.txt", "World!\n");
  readFile(SD, "/hello.txt");
  deleteFile(SD, "/foo.txt");
  renameFile(SD, "/hello.txt", "/foo.txt");
  readFile(SD, "/foo.txt");
  testFileIO(SD, "/test.txt");
*/
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include "esp_vfs_fat.h"
#include "sdmmc_cmd.h"
#include "certs.h"
#include "sdkconfig.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_AMG88xx.h>
//#include <LinearRegression.h>
#include <ESP32Time.h>
////
ESP32Time rtc;
WiFiClient wifiClient;
PubSubClient MQTTclient(mqtt_server, mqtt_port, wifiClient);
Adafruit_AMG88xx amgL;
//Adafruit_AMG88xx amgR;
//LinearRegression lr;
//LinearRegression bgi; //background image
////
const    int pixels           = 64;
const    int toFileSize       = 2500;
const    int payloadSize      = 100;
int      sensorDelay          = 125;
int      count                = 0;
int      mqttOK               = 0;
float    FrameR[pixels] = { 0.0f };
float    FrameL[pixels] = { 0.0f };
float    outsideTemperature   = 0.0f;
//float    dpAtom               = 1.0f / 80.0f; // low/high from data sheet
//float    tsAtom               = 1.0f / 64.0f; // 64 data points 64 time stamps.
//double   valuesModelR[2]      = { 0.0f };
//double   valuesR[2]           = { 0.0f };
//double   valuesModelL[2]      = { 0.0f };;
//double   valuesL[2]           = { 0.0f };
//float    daChange             = 0.0f;
bool     TimeSet              = false;
bool     startTheThing        = false;
QueueHandle_t xQ_Message;
QueueHandle_t Q_toFIle;
////
struct stu_message
{
  char payload [150] = {'\0'};
  String topic;
} x_message;
////
SemaphoreHandle_t sema_MQTT_KeepAlive;
SemaphoreHandle_t sema_mqttOK;
////
////
void IRAM_ATTR mqttCallback(char* topic, byte * payload, unsigned int length)
{
  // clear locations
  memset( x_message.payload, '\0', 150 );
  x_message.topic = ""; //clear string buffer
  x_message.topic = topic;
  int i = 0;
  for ( i; i < length; i++)
  {
    x_message.payload[i] = ((char)payload[i]);
  }
  x_message.payload[i] = '\0';
  xQueueOverwrite( xQ_Message, (void *) &x_message );// send data
} // void mqttCallback(char* topic, byte* payload, unsigned int length)
////
// interrupt service routine for WiFi events put into IRAM
void IRAM_ATTR WiFiEvent(WiFiEvent_t event)
{
  switch (event) {
    case SYSTEM_EVENT_STA_CONNECTED:
      break;
    case SYSTEM_EVENT_STA_DISCONNECTED:
      log_i("Disconnected from WiFi access point");
      break;
    case SYSTEM_EVENT_AP_STADISCONNECTED:
      log_i("WiFi client disconnected");
      break;
    default: break;
  }
} // void IRAM_ATTR WiFiEvent(WiFiEvent_t event)
////
void setup()
{
  
  //  if (!SD.begin())
  //  {
  //    log_i("Card Mount Failed");
  //    return;
  //  }
  //
  String toFile = "";
  toFile.reserve( toFileSize );
  Q_toFIle = xQueueCreate( 5, sizeof(toFile) );
  x_message.topic.reserve(150);
  xQ_Message = xQueueCreate( 1, sizeof(stu_message) );
  //
  sema_mqttOK =  xSemaphoreCreateBinary();
  xSemaphoreGive( sema_mqttOK );
  //
  xTaskCreatePinnedToCore( fSendToFile, "fSendToFile", 9500, NULL, 4, NULL, 1 );
  xTaskCreatePinnedToCore( MQTTkeepalive, "MQTTkeepalive", 3500, NULL, 5, NULL, 1 );
  xTaskCreatePinnedToCore( fparseMQTT, "fparseMQTT", 12000, NULL, 4, NULL, 1 ); // assign all to core 1, WiFi in use.
  xTaskCreatePinnedToCore( fmqttWatchDog, "fmqttWatchDog", 2000, NULL, 3, NULL, 1 ); // assign all to core 1
  xTaskCreatePinnedToCore( fMain, "fMain", 11000, NULL, 3, NULL, 1 ); // assign all to core 1
} // setup()
////
void fMain( void *pvParameters )
{
  while ( !MQTTclient.connected() )
  {
    vTaskDelay( 250 );
  }
  bool status;
  status = amgL.begin(0x68);
  if (!status) {
    log_i( "Could not find a valid AMG88xxL sensor, check wiring!" );
    while (1);
  }
  float theThing = 0.0f;
  TickType_t xLastWakeTime = xTaskGetTickCount();
  const TickType_t xFrequency = sensorDelay; //delay for mS
  String toFile = "";
  toFile.reserve( toFileSize );
  for (;;)
  {
    if ( startTheThing )
    {
      amgL.readPixels( FrameL );
      //collect data
      for (int i = 0; i < pixels; i++)
      {
        theThing = ((float)FrameL[i - 1] * 1.8f) + 32.0f;
        toFile.concat( String(theThing) );
        toFile.concat( "," );
        toFile.concat( String(outsideTemperature) );
        toFile.concat( "," );
        toFile.concat( String( theThing - outsideTemperature) );
        toFile.concat( "\n" );
      }
    }
    if ( toFile.length() != 0 )
    {
      xQueueSend( Q_toFIle, (void *) &toFile, 1 );// send data to sd card handler
    }
    toFile = "";
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
    //log_i( " high watermark %d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete ( NULL );
}
////
void fSendToFile( void * parameter )
{
  String toFile = "";
  toFile.reserve( toFileSize );
  for (;;)
  {
    if ( xQueueReceive(Q_toFIle, &toFile, portMAX_DELAY) == pdTRUE )
    {
      //appendFile(SD, "/readings.txt", toFile.c_str() );
      toFile = "";
    }
    //log_i( " high watermark %d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete( NULL );
}
////
void fmqttWatchDog( void * paramater )
{
  int UpdateImeTrigger = 86400; //seconds in a day
  int UpdateTimeInterval = 86300; // 1st time update in 100 counts
  int maxNonMQTTresponse = 60;
  for (;;)
  {
    vTaskDelay( 1000 );
    if ( mqttOK >= maxNonMQTTresponse )
    {
      ESP.restart();
    }
    xSemaphoreTake( sema_mqttOK, portMAX_DELAY );
    mqttOK++;
    xSemaphoreGive( sema_mqttOK );
    UpdateTimeInterval++; // trigger new time get
    if ( UpdateTimeInterval >= UpdateImeTrigger )
    {
      TimeSet = false; // sets doneTime to false to get an updated time after a days count of seconds
      UpdateTimeInterval = 0;
    }
    //log_i( " high watermark %d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete( NULL );
}
//////
void fparseMQTT( void *pvParameters )
{
  struct stu_message px_message;
  for (;;)
  {
    if ( xQueueReceive(xQ_Message, &px_message, portMAX_DELAY) == pdTRUE )
    {
      if ( px_message.topic == topicOK )
      {
        xSemaphoreTake( sema_mqttOK, portMAX_DELAY );
        mqttOK = 0; // clear mqtt ok count
        xSemaphoreGive( sema_mqttOK );
      }
      if ( !TimeSet )
      {
        String temp = "";
        temp = px_message.payload[0];
        temp += px_message.payload[1];
        temp += px_message.payload[2];
        temp += px_message.payload[3];
        int year =  temp.toInt();
        temp = "";
        temp = px_message.payload[5];
        temp += px_message.payload[6];
        int month =  temp.toInt();
        temp = "";
        temp = px_message.payload[8];
        temp += px_message.payload[9];
        int day =  temp.toInt();
        temp = "";
        temp = px_message.payload[11];
        temp += px_message.payload[12];
        int hour =  temp.toInt();
        temp = "";
        temp = px_message.payload[14];
        temp += px_message.payload[15];
        int min =  temp.toInt();
        rtc.setTime( 0, min, hour, day, month, year );
        log_i( "%s  ", rtc.getTime() );
        TimeSet = true;
      }
      if ( px_message.topic == topicOutsideTemperature )
      {
        startTheThing = true;
        outsideTemperature = String(px_message.payload).toFloat();
      }
    }
    //log_i( " high watermark %d",  uxTaskGetStackHighWaterMark( NULL ) );
  } //for(;;)
  vTaskDelete ( NULL );
} // void fparseMQTT( void *pvParameters )
////
void MQTTkeepalive( void *pvParameters )
{
  sema_MQTT_KeepAlive   = xSemaphoreCreateBinary();
  xSemaphoreGive( sema_MQTT_KeepAlive ); // found keep alive can mess with a publish, stop keep alive during publish
  // setting must be set before a mqtt connection is made
  MQTTclient.setKeepAlive( 90 ); // setting keep alive to 90 seconds makes for a very reliable connection, must be set before the 1st connection is made.
  for (;;)
  {
    //check for a is-connected and if the WiFi 'thinks' its connected, found checking on both is more realible than just a single check
    if ( (wifiClient.connected()) && (WiFi.status() == WL_CONNECTED) )
    {
      xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY ); // whiles MQTTlient.loop() is running no other mqtt operations should be in process
      MQTTclient.loop();
      xSemaphoreGive( sema_MQTT_KeepAlive );
    }
    else {
      log_i( "MQTT keep alive found MQTT status %s WiFi status %s", String(wifiClient.connected()), String(WiFi.status()) );
      if ( !(wifiClient.connected()) || !(WiFi.status() == WL_CONNECTED) )
      {
        connectToWiFi();
      }
      connectToMQTT();
    }
    vTaskDelay( 250 ); //task runs approx every 250 mS
    //log_i( " high watermark %d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete ( NULL );
}
////
void connectToWiFi()
{
  int TryCount = 0;
  while ( WiFi.status() != WL_CONNECTED )
  {
    TryCount++;
    WiFi.disconnect();
    WiFi.begin( SSID, PASSWORD );
    vTaskDelay( 4000 );
    if ( TryCount == 10 )
    {
      ESP.restart();
    }
  }
  WiFi.onEvent( WiFiEvent );
} // void connectToWiFi()
////
void connectToMQTT()
{
  MQTTclient.setKeepAlive( 90 ); // needs be made before connecting
  byte mac[5];
  WiFi.macAddress(mac);
  String clientID = String(mac[0]) + String(mac[4]) ; // use mac address to create clientID
  while ( !MQTTclient.connected() )
  {
    // boolean connect(const char* id, const char* user, const char* pass, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
    MQTTclient.connect( clientID.c_str(), mqtt_username, mqtt_password, NULL , 1, true, NULL );
    vTaskDelay( 250 );
  }
  MQTTclient.setCallback( mqttCallback );
  MQTTclient.subscribe( topicOK );
  MQTTclient.subscribe( mqtt_topic );
} // void connectToMQTT()
////
void writeFile(fs::FS &fs, const char * path, const char * message) {
  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    log_i("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    log_i("File written");
  } else {
    log_i("Write failed");
  }
}
////
void appendFile(fs::FS &fs, const char * path, const char * message) {
  log_i("Appending to file: %s\n", path);
  File file = fs.open(path, FILE_APPEND);
  if (!file)
  {
    log_i("Failed to open file for appending");
    return;
  }
  if (file.print(message))
  {
    log_i("Message appended");
  } else {
    log_i("Append failed");
  }
}
////
void renameFile(fs::FS &fs, const char * path1, const char * path2) {
  log_i("Renaming file %s to %s\n", path1, path2);
  if (fs.rename(path1, path2)) {
    log_i("File renamed");
  } else {
    log_i("Rename failed");
  }
}
////
//void renameFile(fs::FS &fs, const char * path1, const char * path2) {
//  log_i("Renaming file %s to %s\n", path1, path2);
//  if (fs.rename(path1, path2)) {
//    log_i("File renamed");
//  } else {
//    log_i("Rename failed");
//  }
//}
////
void deleteFile(fs::FS &fs, const char * path) {
  log_i("Deleting file: %s\n", path);
  if (fs.remove(path)) {
    log_i("File deleted");
  } else {
    log_i("Delete failed");
  }
}
////
////
void loop() {}