2011-10-27 28 views
0

我有一個串行端口,將通過港口重複使用這種方法:serialport和dispatchertimer,如何讓我的線程在COM端口打開時暫停?

foreach (string s in SerialPort.GetPortNames()) 
{ 
    var serialOneOfMany = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One); 
    if (serialOneOfMany.IsOpen) 
    { 
     serialOneOfMany.Close(); 
    } 
    else 
    { 
     try 
     { 
      serialOneOfMany.Open(); 
     } 
     catch 
     { 

      var openSerial = new System.Timers.Timer(3100); 
      openSerial.Elapsed += (o, e) => 
      { 
       serialOneOfMany.Open(); 
       openSerial.Enabled = false; 

       openSerial.Dispose(); 
      }; 
      openSerial.Enabled = true; 

     }     
    } 

    if (serialOneOfMany.IsOpen) 
    { 
     string received; 

     try 
     { 
      lblPortNum.Content = s; 
      lblPortNum.Refresh(); 


       serialOneOfMany.Write(testMessage); 

      serialOneOfMany.DataReceived += new SerialDataReceivedEventHandler(testSerialPort_DataReceived); 

     } 
     catch (TimeoutException e) 
     { 
      serialOneOfMany.Close(); 
      continue; 
     } 
    } 
} 

所以,我想打開的端口,發送郵件,監聽響應,然後將其關閉。衆所周知,在GetPortNames中找到的每個comport都不是有效的串行端口。所以,我一直在做的是設置了調度定時器的定時器:

DispatcherTimer time = new DispatcherTimer(); 
time.Interval = TimeSpan.FromMilliseconds(3000); 
time.Tick += new EventHandler(someEventHandler); 
time.Start(); 

這裏的另一種方法在這裏處理:

private void someEventHandler(Object sender, EventArgs args) 
{ 
    SerialPort serial = (SerialPort)sender; 
    if (serial.IsOpen) 
     serial.Close(); 
    serial.Dispose(); 

    //if you want this event handler executed for just once 
    DispatcherTimer thisTimer = (DispatcherTimer)sender; 
    thisTimer.Stop(); 
} 

所以,它會打開COM端口,如果在3秒內沒有得到響應,它會關閉端口。我遇到的問題是,foreach循環將通過代碼桶並多次打開comport,我會收到一條消息,指出COM端口已打開並且無法使用。所以基本上它不會在openSerial中暫停。

我希望它打開一個新的串行端口,如果它不可訪問,請等待3100毫秒,然後再試一次。我怎麼做?

更新的代碼:

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    CheckPorts(); 
} 

private void checkPorts() 
{ 
    SendMessage("messageToDevice1", 19200); 
    SendMessage("Message2", 9600); 
} 



private void SendMessage(string testMessage, int baudRate) 
{ 
    int baudRate = 9600; 
    string testMessage = "test"; 
    txtPortName.Text = "Testing all serial ports"; 
    foreach (string s in SerialPort.GetPortNames()) 
    { 
     SerialPort newPort = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One); 
     if (!newPort.IsOpen) 
     { 
      try 
      { 
       newPort.Open(); 
      } 
      catch { } 
     } 
     if (newPort.IsOpen) 
     { 
      openPorts.Add(newPort); 
      newPort.Write(testMessage); 
      newPort.DataReceived += new SerialDataReceivedEventHandler(serialOneOfMany_DataReceived); 
     } 
     else 
     { 
      newPort.Dispose(); 
     } 
    } 
    txtPortName.Text = "Waiting for response"; 
    tmrPortTest.Enabled = true; 
} 

我的新問題是,它只是通過COM口吹,我需要它停止對每個人,花一秒鐘來聽,然後將其關閉。它只是吹過了foreach循環。

現在,我不打開端口並通過所有消息保持打開的原因是我的設備有不同的波特率,我無法調整它們以適應所有匹配。所以,我需要打開端口,然後發送消息,如果它們不響應第一輪消息,然後以新的波特率打開它們併發送新的一批消息,請發送消息。但foreachloop doens不停頓讓我聽。

回答

0

這裏是我會怎麼做 -

首先,試圖打開所有的串行端口。實際上打開的那些被放在一個列表中。

將列表中的所有串行端口分配給相同的DataReceived事件處理程序。事件處理程序是您將節省的端口名稱(它在參數),如果你的rx'd響應

發送的測試消息的所有開放端口

僅有一個定時器終止計時器持續3.1秒

定時器觸發或事件處理程序rx的響應後關閉端口。

1

我認爲這或多或少與罕見的答案一致。您收到回覆的端口(您可能也想檢查回覆)將保持打開狀態,其他所有人都應該關閉。

private List<SerialPort> openPorts = new List<SerialPort>(); 

    private void button3_Click(object sender, EventArgs e) 
    { 
     int baudRate = 9600; 
     string testMessage = "test"; 
     txtPortName.Text = "Testing all serial ports"; 
     foreach (string s in SerialPort.GetPortNames()) 
     { 
      SerialPort newPort = new SerialPort(s, baudRate, Parity.None, 8, StopBits.One); 
      if (!newPort.IsOpen) 
      { 
       try 
       { 
        newPort.Open(); 
       } 
       catch { } 
      } 
      if (newPort.IsOpen) 
      { 
       openPorts.Add(newPort); 
       newPort.Write(testMessage); 
       newPort.DataReceived += new SerialDataReceivedEventHandler(serialOneOfMany_DataReceived); 
      } 
      else 
      { 
       newPort.Dispose(); 
      } 
     } 
     txtPortName.Text = "Waiting for response"; 
     tmrPortTest.Enabled = true; 
    } 

    private void serialOneOfMany_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     txtPortName.Text = ((SerialPort)sender).PortName; 
    } 

    private void tmrPortTest_Tick(object sender, EventArgs e) 
    { 
     tmrPortTest.Enabled = false; 
     foreach (SerialPort port in openPorts) 
     { 
      if (port.PortName != txtPortName.Text) 
      { 
       port.Close(); 
       port.Dispose(); 
      } 
     } 
    } 
+0

它是如此接近。我幾乎在那裏,但我無法弄清楚如何暫停而不阻塞端口。我試過睡覺了,但那只是不好的代碼。如果我只發送一個testMessage,則此代碼有效,但我需要它發送多條消息。 – darthwillard

+0

你爲什麼特別想暫停?您可以使用上述過程來確定哪個端口是正確的。然後,您可以保持打開狀態併發送儘可能多的消息。DataReceived事件已經綁定,因此您將收到任何傳入的消息 - 您只需添加代碼來解釋這些消息。 – Veldmuis