2012-03-28 77 views
6

好的..这将是漫长的,但我需要先解释一些背景。多线程和串口

我的这部分软件是分类顺着传送带上的物品。 我使用Modbus作为传送带。 Modbus将在特定时间打开门,让物品通过门。项目将根据体重通过某些门。

我监测的传感器,以确定何时产品的规模。当传感器被阻塞时,物品被称重并被发送到适当的门。定时器设置为打开/关闭门。

我的代码会为this..the问题的工作是,它不会为多个项目工作。我的意思是,当门打开时,传感器在门关闭之前不被监控。因此,当物品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错误”。

+0

这样的问题DetermineGate(),SetOpenDelay()和SetDuration在规模线程块()?我还没完全理解你的代码。它看起来仍然是非常程序化的,即使你正在使用线程 - 看起来像线程总是在等待着彼此。这是发生了什么? – 2012-03-28 20:31:27

+0

仅供参考,这里是多线程在C#中有很大的联系:http://www.yoda.arachsys.com/csharp/threads/index.shtml – 2012-03-28 20:33:13

+0

这是我第一次多线程。我需要它在我的GUI不锁定的地方。我不确定你的意思是“线程扩展块”线程正在彼此等待。但是当我试图修复它时,我只是遇到了一堆错误(请参阅我的编辑)。我需要这个软件才能运行传送带。它应该以每3秒1次的速度计算传感器传递的物品。所以所有的大门都应该在物品到达门口时打开/关闭。我知道这听起来令人困惑。你明白我想要完成什么吗?感谢您的链接 – CSharpDev 2012-03-28 20:37:57

回答

1

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

+0

我试过这个。我有一个专用于传感器的线程和一个专用于该传感器的线程。如果传感器被堵塞(秤上有东西),秤螺纹只抓住重量。然后,一旦我体重增加,我会产生一条线来处理大门。但我永远不会让它进入该线程,因为我在阅读比例和传感器时遇到了错误。这两个线程不会一起工作。他们在不同的COM端口和一切,所以我不知道怎么回事 – CSharpDev 2012-03-28 20:45:06

+0

我的建议是在启动时启动所有线程,并让它们运行。启动线程很昂贵。让线程连续不断地执行代码是非常昂贵的。然而,让一条线程等待I/O,会比较便宜。不是那么便宜,一个人应该有数百人无缘无故地跑,但便宜到八人通常没什么大不了的。 – supercat 2012-03-29 14:21:42

1

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

编辑补充:你似乎什么是失踪的是,你需要分割,监控规模的代码,并打开和关闭门的代码。要做到这一点的一种方法是有一个无限循环来监视比例,当它检测到某个东西时,它会启动一个处理打开和关闭门的新线程。

+0

感谢查理(和汤姆)为upvote。根据我的理解,我认为这个循环是由一个线程调用另一个线程“引发”的。 – AlexDev 2012-03-28 20:37:09

+0

Gotcha,但然后OP仍在使用过程代码 - 一种方法不会运行,直到其他方法调用它。线程化的思想是让一个代码独立于另一个运行,当它发现一些冗长的代码时(比如打开和关闭门),它会将这些工作转化为新的线程。或者我错过了什么? – 2012-03-28 20:40:20

+0

我循环RunWorkerCompleted方法中的线程。它启动一个定时器,它在滴答后调用线程。 – CSharpDev 2012-03-28 20:48:17

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 
     } 
     } 
    } 
+0

那么newSensor应该如何开始真正的价值?你能详细解释一下你在这里做什么吗? – CSharpDev 2012-03-28 22:03:56

+0

修复了newSensor初始化。正如其他人所建议的那样,这个想法是,传感器线程循环检查传感器,当它检测到状态发生变化时,它会触发标尺线程。 – AlexDev 2012-03-29 11:06:28

+0

我会给这个镜头看看会发生什么。谢谢! – CSharpDev 2012-03-29 12:09:32