serialport和dispatchertimer,如何在com端口打开时让我的线程暂停?

时间:2011-10-27 02:08:09

标签: c# serial-port

我有一个串口,用这种方法迭代端口:

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不会停下来让我听。

2 个答案:

答案 0 :(得分: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();
            }
        }
    }

答案 1 :(得分:0)

以下是我将如何做到这一点 -

首先,尝试打开所有串口。实际上打开的那些放在一个列表中。

将列表中的所有串行端口分配给同一DataReceived事件处理程序。在事件处理程序中,您将保存端口名称(它在args中)并终止计时器如果您响应了该响应

将testMessage发送到所有开放端口

只设置一个计时器3.1秒

一旦计时器触发或事件处理程序rx响应,就关闭端口。