6

好的..这会很长,但我需要先解释一些背景。

我软件的这一部分用于对沿着传送带运行的物品进行分类。我正在为传送带使用 Modbus。Modbus 将在特定时间打开大门,让物品通过大门。物品将根据重量通过某些门。

我正在监控传感器以确定物品何时在秤上。当传感器被阻塞时,物品会被称重并发送到适当的门。定时器设置为打开/关闭大门。

我的代码将适用于此..问题是,它不适用于多个项目。我的意思是,当门打开时,传感器不会被监控,直到门关闭。因此,当物品 A 正在前往登机口的途中,物品 B 在挡住传感器时不会在秤上称重。我一次最多可以有 8 个项目。这是我现在正在运行的代码:

private void SensorThread_DoWork(object sender, DoWorkEventArgs e)
{
    if (SensorThread.CancellationPending == true)
        e.Cancel = true;
    else
    {
        ReadSensor();
    }    
}

private void SensorThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //if sensor is blocked
    if (sensorstatus == 0)
    {
        //the timers just start the thread
        scaleTimer.Start();
    }
    else
    {
        sensorTimer.Start();
    }
}

private void ScaleThread_DoWork(object sender, DoWorkEventArgs e)
{
  if (ScaleThread.CancellationPending == true)
    {
        e.Cancel = true;
    }
    else
    {
        ReadScale();
        //SaveWeight();
        prevgate = gate;
        gate = DetermineGate();
        SetOpenDelay();
        SetDuration();
    }
  }

private void ScaleThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //if gate = 0, this means the weight of meat on scale 
    //is not in any weight range. Meat runs off the end.
    if (gate == 0)
    {
        txtStatus.Invoke(new UpdateStatusCallback(UpdateStatus), new object[] { meatweight.ToString() + 
                                                                                "lbs is out of range"});
        sensorTimer.Start();
    }
    else
    {
      //open gate
      //then close gate
    }
  }

这段代码工作正常,我只需要能够考虑到多个项目就行了。有什么建议么????

我还尝试了以下方法:

private void SensorThread_DoWork(object sender, DoWorkEventArgs e)
{
    if (SensorThread.CancellationPending == true)
        e.Cancel = true;
    else
    {
        ReadSensor();
    }    
}    

private void SensorThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
  sensorTimer.Start();
}

  private void ScaleThread_DoWork(object sender, DoWorkEventArgs e)
{
  if (ScaleThread.CancellationPending == true)
    {
        e.Cancel = true;
    }
    else
    {   
        //sensor blocked
        if (sensorstatus == 0)
        {
          ReadScale();
          //SaveWeight();
          prevgate = gate;
          gate = DetermineGate();
          SetOpenDelay();
          SetDuration();

          //if gate = 0, this means the weight of meat on scale 
          //is not in any weight range. Meat runs off the end.
          if (gate == 0)
          {
            txtStatus.Invoke(new UpdateStatusCallback(UpdateStatus), new object[] { meatweight.ToString() + 
                                                                                "lbs is out of range"});
          }
          else
          {
            //open gate
            //close gate
          }
    }
}

private void ScaleThread_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
   scaleTimer.Start();
}

当我这样做时,我在按下开始按钮时启动了两个线程。我得到各种异常,程序最终抛出 SEHException 并崩溃。我得到的其他错误说“串行端口已打开”或“I/O 错误”。

4

3 回答 3

2

我想你需要这样的东西。不知道是否需要锁,但为了安全起见,我添加了它们,因为您遇到了错误

private void SensorThread_DoWork(object sender, DoWorkEventArgs e) 
{
    int sensor = 1;
    while(!SensorThread.CancellationPending == true) 
    {
        int newSensor;
        lock(this)
        {
            newSensor = ReadSensor(); 
        }

        //sensor state changed
        if(newSensor != sensor)
        {
            //sensor was 1 and changed to 0
            if(newSensor==0)
            {
               scaleTimer.Start(); 
            }
            sensor = newSensor;
        }
        Thread.Sleep(1);
    }
    e.Cancel = true; 
}     

private void ScaleThread_DoWork(object sender, DoWorkEventArgs e) 
{ 
    //sensor blocked 
    //if (sensorstatus == 0) 
    { 
        lock(this)
        {
            ReadScale(); 
        }
        //SaveWeight(); 
        prevgate = gate; 
        gate = DetermineGate(); 
        lock(this)
        {
            SetOpenDelay(); 
            SetDuration(); 
        }

      //if gate = 0, this means the weight of meat on scale  
      //is not in any weight range. Meat runs off the end. 
      if (gate == 0) 
      { 
        txtStatus.Invoke(new UpdateStatusCallback(UpdateStatus), new object[] { meatweight.ToString() +  
                                                                            "lbs is out of range"}); 
      } 
      else 
      { 
        lock(this)
        {
        //open gate 
        }
        lock(this)
        {
        //close gate 
        }
      } 
  } 
于 2012-03-28T21:30:10.663 回答
1

我建议您最好的选择可能是创建一个专用线程来坐在每个串行端口上。这种方法既不要求也不禁止端口处理方式的任何相似性,将避免端口之间的任何操作干扰,并且将在合理范围内可扩展(对 32 个端口中的每一个使用一个线程就可以了;使用1,000 个线程中的每一个都不好)。尽管应该避免创建只会运行短时间并退出的线程,或者创建非常大量的线程,但为每个串行端口使用专用线程将确保当数据进入时将有一个线程准备好处理它。

于 2012-03-28T20:34:39.860 回答
1

我注意到您的线程的 DoWork 方法中没有任何循环。那将是一个很好的起点。工作线程应该是一个在 CancellationPending 设置为 true 之前不会返回的循环。它们不会仅仅因为您将它放在一个线程中而自行循环 - 线程将运行直到它完成,然后退出。

编辑添加:您似乎缺少的是您需要拆分监控秤的代码和打开和关闭大门的代码。一种方法是设置一个无限循环来监控秤,当它检测到某些东西时,它会启动一个新线程来处理门的打开和关闭。

于 2012-03-28T20:35:42.263 回答