如何在COM端口发送和接收之间进行协调?

时间:2014-12-16 00:50:05

标签: c# serial-port compact-framework port windows-ce

我试图重构一些超复杂的遗留代码,这些代码将数据从手持设备发送到手持设备所连接的PC上运行的应用程序。

有一个"对话"在遵循协议的两个应用程序之间进行;服务器(在PC上运行的应用程序)根据客户端告诉它的响应,反之亦然。实际上,"对话"可以看到大约三分之二here

无论如何,我的问题是:如何让客户端等待服务器响应而不中断它,或者认为它不会响应并且无法继续?这就是我现在所拥有的:

public class FileXferLegacy : IFileXfer
{
    private SerialPort cereal;
    private String lastDataReceived;
    private String receivedData;

    . . .

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        // This method will be called when there is data waiting in the port's buffer
        try
        {
            receivedData += cereal.ReadLine();
            lastDataReceived = receivedData;
            ExceptionLoggingService.Instance.WriteLog(String.Format("Received {0} in FileXferLegacy.SendDataContentsAsXML", receivedData));
        }
        catch (Exception ex)
        {
            //MessageBox.Show(ex.Message);
        }
    }

    #region IFileFetchSend Members

    . . .

    public void SendDataContentsAsXML(string destinationPath, string data)
    {
        byte[] stuff;
        ExceptionLoggingService.Instance.WriteLog("Reached 
FileXferLegacy.SendDataContentsAsXML");
        cereal.Open();
        stuff = System.Text.UTF8Encoding.UTF8.GetBytes("PING" + "\n");
        cereal.Write(stuff, 0, stuff.Length);
        if (lastDataReceived.Contains("PING")) // Expecting "PING|ACKNOWLEDGE|"
        {
            stuff = 
System.Text.UTF8Encoding.UTF8.GetBytes("LOGIN|foo|000003|LOC_HOST|PPP_PEER|1.4.0.42|bar" + "\n"); 
// TODO: replace this test data with dynamic data
            cereal.Write(stuff, 0, stuff.Length);
        }
        if (lastDataReceived.Contains("JOIN|LEVEL")) // Expecting something like "JOIN|LEVEL|1 
SETTING|ALT_ID|FALSE"
        {
            stuff = System.Text.UTF8Encoding.UTF8.GetBytes("HHTCOMMAND|GETHHTSUPDATE|"); 
            cereal.Write(stuff, 0, stuff.Length);
        }
        . . .
        String lastResponse = lastDataReceived; // Expecting something like 
"RESULT|FILECOMPLETE|INV_000003_whatever(not identical to what was sent earlier!).XML"
        // Parse out and do something with the filename ("INV_000003_whatever(not identical to 
what was sent earlier!).XML" above)
    }

如您所见,客户端/掌上电脑发送一个字符串;然后读取" lastDataReceived"在DataReceived方法中分配的。但是,如果出现延迟," lastDataReceived"一片空白?我需要做些什么来强制延迟(没有达到会导致应用程序在缓慢中呈现懒惰状态的极端)?或者,如果我完全偏离基础,应该采取什么方式?

2 个答案:

答案 0 :(得分:2)

一种典型的方法是使用一个读取器线程,通过阻塞读取从端口拉出字节(尽管可以通过异步通知完成),并且一旦检测到整个消息已经传递,它就会:

  1. 将它们放入阻塞队列(消费者阻止对出列的呼叫进行出列,直到添加了一个msg或达到超时
    1. 通过包含该消息的事件通知侦听器。
    2. 这两个中的哪一个很大程度上取决于这些消息的消费者。上面的代码将受益于#1,但如果消费者是UI线程,那么你应该看#2。

答案 1 :(得分:2)

该协议似乎是半双工的,因此使用Write / Readline的同步调用重写它似乎是处理它的最简单方法。