2015-03-29 7 views
2

Я пишу программу, которая прослушивает последовательный порт. У меня уже есть код, который использует драйверы VCP (Virtual COM Port), чтобы открыть последовательное соединение, а затем добавить обработчик событий для получения любых данных времени. Этот код выглядит примерно так:Как я могу использовать EventWaitHandle для создания события?

public void OpenPort(string portNumber) 
{ 
    _port = new SerialPort(
     portName: portNumber, 
     baudRate: 9600, 
     parity: Parity.None, 
     dataBits: 8, 
     stopBits: StopBits.One 
    ); 
    _port.DataReceived += ReadData; 
} 

private void ReadData(object sender, SerialDataReceivedEventArgs e) 
{ 
    string data = _port.ReadExisting().Trim(); 
    Console.WriteLine("Received: " + data); 
} 

Это прекрасно работает. Мне очень легко понять, как настроить события, используя нотацию +=. Но я пытаюсь переключиться с использования драйверов VCP вместо этого, используя D2XX drivers, предоставленный FTDI. У меня есть большая часть эквивалентного кода, который мне нужно написать, за исключением того, что он может читать данные всякий раз, когда происходит событие, полученное «данные».

Драйвер D2XX включает в себя один способ настройки обработчиков событий при получении данных, который называется SetEventNotification. Вот что сигнатура метода выглядит следующим образом:

SetEventNotification(UInt32 eventMask, EventWaitHandle eventHandle); 

Первый параметр достаточно прямолинейно (у них есть некоторые предопределенные uints вы можете пройти, чтобы определить, когда событие должно вызвать), но я никогда не работал непосредственно с EventWaitHandles раньше, и я обнаружил, что the documentation сложно понять, так что мне трудно начать работу.

В конце дня ... Я хотел бы иметь метод прослушивателя событий, который выполняет задачу чтения, и которую я могу назначить с помощью оператора +=, как это было выше с драйвером VCP.

Основываясь на том, что я читал, похоже, что мне нужно будет создать новый Thread, который, по существу, непрерывно проверяет сигнал EventWaitHandle? Или что-то типа того? Любые примеры или пример кода, чтобы начать меня (или закончил!), Будут оценены.

Вот что я до сих пор:

public void OpenPort(string portNumber) 
{ 
    _port = new FTDI(); 
    var status = _port.OpenBySerialNumber(portNumber); 
    if (FTDI.FT_STATUS.FT_OK != status) throw new Exception(); 

    status = _port.SetBaudRate((UInt32) 9600); 
    if (FTDI.FT_STATUS.FT_OK != status) throw new Exception(); 

    status = _port.SetDataCharacteristics(
     DataBits: FTDI.FT_DATA_BITS.FT_BITS_8, 
     StopBits: FTDI.FT_STOP_BITS.FT_STOP_BITS_1, 
     Parity: FTDI.FT_PARITY.FT_PARITY_NONE 
    ); 
    if (FTDI.FT_STATUS.FT_OK != status) throw new Exception(); 

    var evHandle = new EventWaitHandle(false, EventResetMode.AutoReset, ""); 
    _port.SetEventNotification(FTDI.FT_EVENTS.FT_EVENT_RXCHAR, evHandle); 

    // ... now what? 
} 

public void ReadData(object sender, EventArgs e) 
{ 
    UInt32 bytesAvailable = 0; 
    _port.GetRxBytesAvailable(ref bytesAvailable); 

    string data; 
    UInt32 bytesRead = 0; 
    _port.Read(out data, bytesAvailable, ref bytesRead); 

    data = data.Trim(); 
    Console.WriteLine("Received: " + data); 
} 

ответ

2

Я должен создать новую тему, которая по существу опрашивает непрерывно сигналу EventWaitHandle в

Опросы, нет. Но ждет, да. Все, что может сделать обработчик событий, это позволить потоку спящего режима до тех пор, пока событие не будет сигнализировано. Обратите внимание, что «событие» здесь означает нечто совершенно отличное от C# «событие», хотя, конечно, вы можете использовать его как часть реализации последнего.

Честно говоря, совсем не ясно, почему вы направляетесь по этой части. Вы имеете дело с данными, передаваемыми через стандартный последовательный порт? Если это так, то никогда не должно быть необходимости использовать какой-либо сторонний API; Windows и .NET предоставляют все, что вам нужно, и вы должны придерживаться этого. Что делает использование этого стороннего API, что вы не можете выполнить с помощью стандартного класса SerialPort?

Что касается самого события, без какого-либо контекста (и нет, вряд ли кто-то просеял бы через PDF, который вы связали, чтобы выяснить, как создать для вас решение под ключ), все, что можно предложить, это общий план того, как вы можете использовать ручку событий для реализации события:

public event EventHandler DataReceived; 

private bool _done; 

private void PortListener(EventWaitHandle waitHandle) 
{ 
    while (true) 
    { 
     waitHandle.WaitOne(); 
     if (_done) 
     { 
      break; 
     } 

     EventHandler handler = DataReceived; 

     if (handler != null) 
     { 
      handler(this, EventArgs.Empty); 
     } 
    } 
} 

public void StartListening(EventWaitHandle waitHandle) 
{ 
    _done = false; 
    new Thread(() => PortListener(waitHandle)).Start() 
} 

public void StopListening(EventWaitHandle waitHandle) 
{ 
    _done = true; 
    waitHandle.Set(); 
} 

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

Чтобы сделать это, он просто поддерживает внутренний флаг _done указывающий, является ли поток должен быть запущен или нет, и предоставляет Start... и Stop... методы, которые очистить флаг и начать нить с петлей, и установить флаг и сигнализировать событие, соответственно.

+0

Большое вам спасибо! Это прекрасно и дает мне достаточно, чтобы написать остальные. (Я бы не ожидал, что кто-нибудь сможет проскочить через этот неясный PDF-файл!) Чтобы решить ваши проблемы, нет, я фактически не отправляю данные по стандарту COM-порта, а вместо этого использую кабель USB-последовательный (эффективно эмулируя последовательная связь). Есть несколько документированных недостатков в использовании драйверов VCP, потому что, хотя они имеют более удобный интерфейс программирования, они могут фактически вызывать исключения на уровне структуры, которые вы не можете поймать, и тому подобное. Методы FTDI, как правило, более надежны. – SoaperGEM

Смежные вопросы