2012-03-28 43 views
6

Ok .. điều này sẽ kéo dài nhưng tôi cần giải thích một số nền trước.Đa luồng và Cổng nối tiếp

Phần này của phần mềm của tôi là để sắp xếp các mục chạy xuống băng tải. Tôi đang sử dụng Modbus cho băng tải. Modbus sẽ mở các cổng tại một thời điểm cụ thể để cho một mục đi qua cổng. Vật phẩm sẽ đi qua một số cổng dựa trên trọng lượng.

Tôi đang theo dõi một cảm biến để xác định thời điểm một mục trên thang đo. Khi cảm biến bị chặn, vật phẩm được cân và gửi đến cổng thích hợp. Bộ hẹn giờ được đặt để mở/đóng cổng.

Mã của tôi sẽ hoạt động cho vấn đề này..có vấn đề, nó sẽ không hoạt động đối với nhiều mục. Bởi vì tôi có nghĩa là, trong khi một cổng được mở, cảm biến không được giám sát cho đến khi cổng được đóng lại. Vì vậy, trong khi mục A đang trên đường đến cổng, mục B sẽ không bị cân nặng trên quy mô khi nó chặn cảm biến. Tôi có thể có tối đa 8 mục trên cùng một lúc. Đây là mã tôi đang chạy ngay bây giờ:

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

Mã này hoạt động tốt, tôi chỉ cần có thể tính đến nhiều mục trên dòng. Mọi đề xuất ????

Tôi cũng đã thử như sau:

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(); 
} 

Khi tôi đã làm điều này, tôi bắt đầu cả hai đề khi nút bắt đầu được nhấn. Tôi nhận được tất cả các loại ngoại lệ và chương trình cuối cùng ném SEHException và treo. Các lỗi khác tôi nhận được nói "Cổng nối tiếp đã được mở" hoặc "Lỗi I/O".

+0

Có phải vấn đề mà chuỗi quy mô chặn trong khi xác định(), SetOpenDelay() và SetDuration()? Tôi chưa hoàn toàn hiểu mã của bạn. Dường như nó vẫn còn rất thủ tục ngay cả khi bạn đang sử dụng các chủ đề - có vẻ như các chủ đề luôn chờ đợi lẫn nhau. Đây có phải là những gì đang xảy ra không? –

+0

FYI, đây là một liên kết tuyệt vời về đa luồng trong C#: http://www.yoda.arachsys.com/csharp/threads/index.shtml –

+0

Đây là lần đầu tiên đa luồng của tôi.Tôi cần nó, nơi GUI của tôi sẽ không bị khóa. Tôi không chắc chắn những gì bạn có nghĩa là bởi "các khối quy mô thread" Các chủ đề đang chờ đợi nhau .. nhưng khi tôi cố gắng sửa chữa nó, tôi chỉ có một loạt các lỗi (xem chỉnh sửa của tôi). Tôi cần phần mềm này để có thể chạy một băng tải. Nó nên tính toán cho các mục đi qua các cảm biến với tốc độ nói ... 1 mục mỗi 3 giây. Vì vậy, tất cả các cửa nên được mở/đóng cửa khi mặt hàng đến cửa của nó. Tôi biết điều này nghe có vẻ khó hiểu .. bạn có hiểu những gì tôi đang cố gắng thực hiện không? Cảm ơn bạn đã liên kết – CSharpDev

Trả lời

1

Tôi khuyên bạn nên đặt cược tốt nhất có thể là tạo một chuỗi chuyên dụng để ngồi trên mỗi cổng nối tiếp. Cách tiếp cận như vậy sẽ không yêu cầu, cũng không cấm, bất kỳ sự tương đồng nào về cách xử lý các cổng, sẽ tránh bất kỳ sự can thiệp nào giữa các cổng và sẽ có thể mở rộng trong giới hạn hợp lý (sử dụng một chuỗi cho 32 cổng); một chủ đề cho mỗi 1.000 sẽ là xấu). Mặc dù chúng ta nên tránh tạo các luồng chỉ đơn giản là chạy trong một thời gian ngắn và thoát, hoặc tạo một số lượng lớn các luồng, sử dụng một chuỗi chuyên dụng cho mỗi cổng nối tiếp sẽ đảm bảo rằng khi dữ liệu đến trong đó sẽ có một luồng sẵn sàng để xử lý nó.

+0

Tôi đã cố gắng thực hiện điều này. Tôi có một sợi chỉ dành riêng cho cảm biến và một cái dành riêng cho quy mô. Các chủ đề quy mô chỉ nắm lấy trọng lượng nếu cảm biến đã bị chặn (một cái gì đó trên quy mô). Sau đó, một khi tôi nhận được trọng lượng tôi sẽ đẻ trứng một sợi để xử lý các cửa. Tôi sẽ không bao giờ làm cho nó vào chủ đề đó mặc dù bởi vì tôi có lỗi với đọc quy mô và cảm biến. Hai chủ đề đó sẽ không hoạt động cùng nhau. Họ đang trên cổng COM khác nhau và tất cả mọi thứ, vì vậy tôi không chắc chắn whats lên – CSharpDev

+0

đề nghị của tôi sẽ có được để khởi động tất cả các chủ đề lúc khởi động và chỉ đơn giản là để chúng chạy. Bắt đầu từ chủ đề là tốn kém. Để lại một chuỗi liên tục thực thi mã vô ích là rất tốn kém. Tuy nhiên, việc đặt một chủ đề bị chặn chờ I/O, rẻ hơn nhiều. Không phải rẻ đến nỗi người ta phải có hàng trăm người chạy không vì lý do gì, nhưng đủ rẻ đến mức tám người nói chung sẽ không có vấn đề gì lớn. – supercat

1

Tôi nhận thấy rằng bạn không có bất kỳ vòng lặp nào trong các phương pháp DoWork của luồng. Đó sẽ là một nơi tuyệt vời để bắt đầu. Chuỗi công nhân phải là một vòng lặp không trả lại cho đến khi CancellationPending được đặt thành true. Chúng sẽ không tự lặp lại chỉ bởi vì bạn có nó trong một luồng - luồng sẽ chạy cho đến khi nó được thực hiện, sau đó thoát ra.

Đã chỉnh sửa để thêm: Những gì bạn dường như bị thiếu là bạn cần chia nhỏ mã theo dõi tỷ lệ và mã mở và đóng cổng. Một cách để làm điều đó sẽ là có một vòng lặp vô hạn để theo dõi quy mô, và khi nó phát hiện ra thứ gì đó, nó bắt đầu một luồng mới xử lý việc mở và đóng cửa.

+0

Cảm ơn Charlie (và Tom) về sự thăng hoa. Từ những gì tôi hiểu tôi nghĩ rằng vòng lặp là "gây ra" bởi một thread gọi khác. – AlexDev

+0

Gotcha, nhưng sau đó OP vẫn đang sử dụng mã thủ tục - một phương pháp sẽ không chạy cho đến khi phương thức khác gọi nó. Ý tưởng trong luồng là có một mã chạy độc lập với mã khác, và khi nó tìm thấy cái gì đó dài (như mở và đóng cửa), nó sinh ra công việc đó thành một luồng mới. Hay tôi đang thiếu một cái gì đó? –

+0

Tôi lặp lại chuỗi trong phương thức RunWorkerCompleted. Nó bắt đầu một bộ đếm thời gian gọi các chủ đề sau khi nó ve. – CSharpDev

2

Tôi nghĩ bạn cần một cái gì đó như thế này. Không biết liệu ổ khóa có cần thiết hay không nhưng tôi đã thêm chúng cho an toàn vì bạn đang gặp lỗi

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

Vậy newSensor có nên bắt đầu như một giá trị thực sự không? bạn có thể xây dựng một chút về những gì bạn đang làm ở đây không? – CSharpDev

+0

Đã sửa lỗi khởi tạo Bộ khởi động mới. Ý tưởng, như những người khác đã gợi ý, là các vòng lặp của bộ cảm biến kiểm tra cảm biến và khi nó phát hiện một sự thay đổi trong trạng thái nó kích hoạt các sợi quy mô. – AlexDev

+0

Tôi sẽ chụp ảnh này và xem điều gì sẽ xảy ra. Cảm ơn! – CSharpDev

Các vấn đề liên quan