首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多线程和串行端口

多线程和串行端口
EN

Stack Overflow用户
提问于 2012-03-29 04:12:58
回答 3查看 2K关注 0票数 6

Ok..this将会很长,但我需要先解释一些背景知识。

我的这部分软件是用来分拣从传送带上跑下来的物品的。我正在使用Modbus作为传送带。Modbus会在特定时间打开门,让物品通过门。物品会根据重量通过一定的闸门。

我正在监测一个传感器,以确定物品是否在天平上。当传感器被阻塞时,该物品被称重并被送到适当的闸门。定时器设置为打开/关闭闸门。

我的代码将工作的this..the问题是,它不会工作的多个项目。我的意思是,当门打开时,传感器不会被监控,直到门关闭。因此,当物品A在去登机口的路上,当物品B挡住传感器时,它不会在天平上称重。我一次最多可以有8个项目。下面是我现在运行的代码:

代码语言:javascript
复制
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
    }
  }

这段代码运行得很好,我只需要能够处理行上的多个项目。有什么建议吗?

我还尝试了以下几种方法:

代码语言:javascript
复制
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();
}

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

EN

回答 3

Stack Overflow用户

发布于 2012-03-29 05:30:11

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

代码语言:javascript
复制
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 
        }
      } 
  } 
票数 2
EN

Stack Overflow用户

发布于 2012-03-29 04:34:40

我建议您最好的办法是在每个串行端口上创建一个专用线程。这样的方法既不需要也不禁止在如何处理端口方面有任何相似之处,将避免端口之间的任何操作干扰,并且将在合理的范围内可扩展( 32个端口中的每个端口使用一个线程就可以了;1000个端口中的每个端口使用一个线程就不好了)。虽然人们应该避免创建只会运行很短时间然后退出的线程,或者创建真正大量的线程,但为每个串行端口使用专用线程将确保当数据进入时,会有一个线程准备好处理它。

票数 1
EN

Stack Overflow用户

发布于 2012-03-29 04:35:42

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

编辑后添加:您似乎缺少的是,您需要将监视规模的代码与打开和关闭门的代码分开。要做到这一点,一种方法是有一个无限循环来监控规模,当它检测到一些东西时,它会启动一个新的线程来处理门的打开和关闭。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9914948

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档