2016-12-26 58 views
0

我正在使用串行端口從for循環迭代中的設備獲取數據。 問題是在循環迭代中,我需要從串口獲取數據,驗證它並轉到下一次迭代。 我怎麼能做到這一點?C#等待,直到收到數據並轉到下一次迭代

這裏是我的代碼:

private void processData() 
{ 
    // Loop Procedure 
    int x = Int32.Parse(master["Cycle"].ToString()); 
    int y = Int32.Parse(master["MinWeight"].ToString()); 

    // Loop for each line 
    for (int i = this.CLine; i < 2; i++) 
    { 
     this.CLine = i; 
     if (i == 0) 
      label15.Text = master["LLINE"].ToString(); 
     else 
      label15.Text = master["RLINE"].ToString(); 

     IDictionary<string, string> dic = (Dictionary<String, String>)master[i.ToString()]; 
     label18.Text = this.CProcess = dic["PROCESSID"]; 
     int z = Int32.Parse(dic["PRODLANE"].ToString()); 

     // Loop for each sampling session (Cycle) 
     for (int j = this.CCycle; j <= x; j++) 
     { 
      this.CCycle = j; 

      // Loop for production lane 
      for (int k = this.CLane; k <= z; k++) 
      { 
       this.CLane = k; 
       label16.Text = k.ToString(); 


       // In this section i want to send command over serial port 
       // get value from my device 
       // validate it if current weight bellow standard weight 
       // do it again (get data from device) 
       // else we can go to next iteration 

       while (this.CWeight < y) 
       { 
        XApi.l("xxx2 " + this.CWeight + " vs " + y + " " + k.ToString() + " " + this.isDataReady); 
        SendData("Q"); 
       } 

       // Commit Transaction 
       // XDb.CommitTrans(this.CCycle.ToString(), dic["LINEID"].ToString(), this.CLane.ToString(), weight.ToString(), this.isTrialStage == true ? "1" : "0"); 
      } 
     } 
    } 
} 

我已經試過這

while (this.CWeight < y) 
{ 
    XApi.l("xxx2 " + this.CWeight + " vs " + y + " " + k.ToString() + " " + this.isDataReady); 
    SendData("Q"); 
} 

但似乎阻塞UI線程,讓我的應用程序solaggy。 任何人都可以給我一些想法?提前致謝。

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
{ 
    if (e.EventType == System.IO.Ports.SerialData.Eof) 
     return; 

    // If the com port has been closed, do nothing 
    if (!comport.IsOpen) 
     return; 

    // Update flag data received 
    this.isDataReady = true; 

    // Determain which mode (string or binary) the user is in 
    if (CurrentDataMode == DataMode.Text) 
    { 
     // Read all the data waiting in the buffer 
     string data = comport.ReadExisting(); 

     // Update result   
     result += data; 

     if (result.Length > 16) 
     { 
      SetText(result.ToString()); 
     } 

     // Display the text to the user in the terminal 
     Log(LogMsgType.Incoming, data); 
    } 
    else 
    { 
     // Obtain the number of bytes waiting in the port's buffer 
     int bytes = comport.BytesToRead; 

     // Create a byte array buffer to hold the incoming data 
     byte[] buffer = new byte[bytes]; 

     // Read the data from the port and store it in our buffer 
     comport.Read(buffer, 0, bytes); 

     // Show the user the incoming data in hex format 
     Log(LogMsgType.Incoming, ByteArrayToHexString(buffer)); 
    } 
} 

private void SendData(String msg) 
    { 
     this.isDataReady = false; 
     result = ""; 
     if (CurrentDataMode == DataMode.Text) 
     { 
      // Send the user's text straight out the port 
      comport.Write(msg + "\r\n"); 

      // Show in the terminal window the user's text 
      Log(LogMsgType.Outgoing, msg + "\n"); 
     } 
     else 
     { 
      try 
      { 
       // Convert the user's string of hex digits (ex: B4 CA E2) to a byte array 
       byte[] data = HexStringToByteArray(txtSendData.Text); 

       // Send the binary data out the port 
       comport.Write(data, 0, data.Length); 

       // Show the hex digits on in the terminal window 
       Log(LogMsgType.Outgoing, ByteArrayToHexString(data) + "\n"); 
      } 
      catch (FormatException) 
      { 
       // Inform the user if the hex string was not properly formatted 
       Log(LogMsgType.Error, "Not properly formatted hex string: " + txtSendData.Text + "\n"); 
      } 
     } 
    } 
+0

你需要使用委託。我在這裏寫了一個很好的例子:http://stackoverflow.com/a/38536373/2009197 你可能不需要一個完整的狀態機,但這應該把你放在正確的軌道上。 – Baddack

回答

2

任何人都可以給我一些想法?

你可以在你的代碼中使用async/await不要通過編寫像下面這樣的擴展方法來阻止你的UI。用法是:

async void SomeMethod() 
{ 
    SerialPort serialPort = ....... 

    while (true) 
    { 
     serialPort.Write(.....); 
     var retval = await serialPort.ReadAsync(); 
    } 

} 

這裏的關鍵字用TaskCompletionSource類與事件......


static public class SerialPortExtensions 
{ 
    public static Task<byte[]> ReadAsync(this SerialPort serialPort) 
    { 
     var tcs = new TaskCompletionSource<byte[]>(); 
     SerialDataReceivedEventHandler dataReceived = null; 
     dataReceived = (s, e) => 
     { 
      serialPort.DataReceived -= dataReceived; 
      var buf = new byte[serialPort.BytesToRead]; 
      serialPort.Read(buf, 0, buf.Length); 
      tcs.TrySetResult(buf); 
     }; 
     serialPort.DataReceived += dataReceived; 
     return tcs.Task; 
    } 
} 
+0

但我需要在我自己的迭代中驗證數據,你的代碼是否可以實現這一點? (int k = this.CLane;k≤z; k ++) { this.CLane = k; label16.Text = k.ToString(); //在本節中,我想通過串行端口發送命令 //從我的設備獲得價值 – NPE

+0

@NPE它會返回所有可用數據,如同步代碼,但不會阻止調用線程....因此,無論檢查您想.... –

+0

我已經檢查使用異步和任務可以通過vs2012,我的編碼環境使用vs2010完成。任何其他想法? – NPE

相關問題