оставляя переменные вне цикла while - PullRequest
0 голосов
/ 09 августа 2011

Я получаю от последовательного порта (VHF-приемник) некоторые данные из разных источников, например, автомобили. Вся программа на данный момент представляет собой цикл while. Пока порт открыт, я получаю байты в массивах и делаю некоторую расшифровку. Каждый цикл сообщения while loop 1 принимается и декодируется. Но в одном случае есть сообщение, которое разбивается на части нечетной части и четной части. Мне нужно и то, и другое, чтобы декодировать сообщение, но в 1 получена только одна часть, а цикл, скажем, нечетная часть из car1 . Следующий цикл while может содержать нечетную часть из car2 или четную часть из car1 или четную часть из car3 и т. Д. Поэтому мне нужен способ хранения нечетных четных частей каждого машина, пока оба они не получены. И еще одна важная вещь: должно быть 10-секундное временное окно с момента, когда я получу первую часть, до момента, когда я получу вторую часть. Если пройдет 10 секунд, первая часть должна быть удалена. Я думаю, что массивы не будут работать, потому что мне нужно что-то динамическое, например, List или словарь.

while (serialportopen)
{
//somedecoding I end up with
string hexid;
string oddpart;
string evenpart;
}

Я пытался создать класс , подобный этому со свойствами для хранения частей сообщения, но я не могу создать объект с именем hexid, потому что он уже объявлен. Любые идеи, включая списки словарей или классов?

Ответы [ 2 ]

1 голос
/ 09 августа 2011

То, как большинство систем делают это при работе с сегментами данных переменной длины, заключается в том, что в первом проходящем пакете есть что-то уникальное, что уведомляет принимающий драйвер о том, что он состоит из двух частей. Например, это может быть просто MSB (старший значащий бит), установленный или не установленный в первом пакете, где 0 может означать, что второго пакета нет, а 1 может означать, что существует второй пакет. Тогда нужно просто замаскировать его, когда вы его получите, и вызвать функцию для получения второй части, или установить флаг, что вторая часть должна быть получена, и что это НЕ новый пакет.

Что касается области видимости, я немного туманен в отношении того, что вы спрашиваете, но на основании приведенного выше кода, если вы объявляете переменные вне цикла, т. Е .:

string hexid;
string oddpart;
string evenpart;
while (serialportopen)
{

}

Они будут поддерживать область действия для нескольких итераций цикла. Лучше делать это независимо от того, что она не будет повторно объявлять переменную каждый раз. Это может или не может быть оптимизировано компилятором.

В противном случае в битовой структуре этого пакета есть что-то уникальное, что уведомляет драйвер о необходимости другого пакета. В этом пакете может быть код операции или поле команды, это может быть просто проблемой маскировки, вызывающей функцию для извлечения и возврата второй части, т. Е.

if ((command & CERTAIN_PACKET) == CERTAIN_PACKET)
    odpart = GetSecondPart();

Надеюсь, это вам поможет!

0 голосов
/ 09 августа 2011

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

Dictionary<string, string> oddParts = new Dictionary>string, string>();
Dictionary<string, Timer> timers = new Dictionary<string, Timer>();
while (serialportopen)
{
    // somedecoding I end up with
    string hexid;
    string oddpart;
    string evenpart;
    // you need something to identify where the message came from and that is present in both the odd and even part (the BF... of your previous question)
    string msgId;
    if (!String.IsNullOrEmpty(oddpart))
        ProcessOddPart(msgId, oddpart, oddParts, timers);
    else if (!String.IsNullOrEmpty(evenpart))
        hexid = HexIdFromEvenPart(msgId, evenpart, oddparts, timers);
    if (!String.IsNullOrEmpty(hexid))
        Process(hexid);
}

void Process(string hexid)
{
    // your stuff here
}

void ProcessOddPart(string msgId, string oddPart, Dictionary<string, string> oddParts, Dictionary<string, Timer> timers)
{
    oddParts[msgId] = oddPart;
    System.Timers.Timer tmr = new Timer(); 
    timers[msgId = tmr;
    ElapsedEventHandler timePassed = delegate(object anObj, ElapsedEventArgs args) {
        tmr.Stop();
        oddParts.Remove(msgId);
        timers.Remove(msgId);
    };
    tmr.Interval = 10000;
    tmr.Elapsed += timePassed;
    tmr.Start();
}

void HexIdFromEvenPart(string msgId, string evenPart, Dictionary<string, string> oddParts, Dictionary<string, Timer> timers)
{
    string oddPart;
    Timer tmr;
    if (timers.TryGetValue(msgId, out tmr))
    {
        tmr.Stop();
        timers.Remove(msgId);
    }
    if (!oddParts.TryGetValue(msgId, out oddPart))
        return null;
    return oddPart + evenPart;
}
...