serialport и dispatchertimer, как заставить мой поток приостановиться, когда com порт открыт? - PullRequest
0 голосов
/ 27 октября 2011

У меня есть последовательный порт, который будет проходить через порты следующим способом:

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 компорт не является действительным последовательным портом.Итак, что я делал, так это установил таймер с таймером диспетчера:

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

так, он откроет компорт, если он не получит ответ в течение 3 секунд, он закроет порт.у меня проблема в том, что цикл foreach будет просто перемещаться по коду и открывать компорт несколько раз, я получу сообщение о том, что 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;
}

Моя новая проблема заключается в том, что он просто дует через ком-порты, мне нужно, чтобы он остановился для каждого, потребуется секунда, чтобыслушай, затем закрой его.это просто дует через цикл foreach.

Теперь причина, по которой я не просто открываю порт и держу его открытым во всех сообщениях, заключается в том, что мои устройства имеют разную скорость передачи данных, и я не могу настроить их для всех совпадений.Итак, мне нужно открыть порты, затем отправить сообщения, прослушать, если они не отвечают на первый раунд сообщений, затем открыть их на новой скорости передачи и отправить новый пакет сообщений.но foreachloop не делает паузу для меня, чтобы слушать.

Ответы [ 2 ]

1 голос
/ 27 октября 2011

Я думаю, что это более или менее согласуется с редким ответом. Порт, на который вы получаете ответ (вы, вероятно, также захотите проверить ответ), останется открытым, а все остальные должны быть закрыты.

    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 голосов
/ 27 октября 2011

Вот как бы я это сделал -

Сначала попробуйте открыть все последовательные порты. Те, которые действительно открыты, помещаются в список.

Назначить все последовательные порты в списке одному и тому же обработчику событий DataReceived. В обработчике событий вы сохраните имя порта (оно в аргументах) и убьете таймер , если вы ответили

Отправьте свое тестовое сообщение на все открытые порты

Установить только один таймер на 3,1 секунды

Закройте порты, как только таймер сработает или обработчик событий получит ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...