Принудительное завершение BeginWrite в приложении ввода-вывода последовательного COM-порта с помощью BaseStream - PullRequest
0 голосов
/ 14 июля 2009

У меня есть программа на C #, которая связывается с последовательными устройствами, используя построен в классе SeralPort. Тем не менее, я хочу делать асинхронные записи и для этого я использую BaseStream.BeginWrite (). В асинхронном обратном вызове Я вызываю BaseStream.EndWrite (). Все это прекрасно работает. Однако иногда Я хочу закрыть порт ДО того, как BeginWrite () завершится, но вызов Close () заставляет его зависать, пока BeginWrite () находится в состоянии ожидания. Я пытался вызвать EndWrite (), но он также зависает, если BeginWrite () находится на рассмотрении. Как убить поток BeginWrite ()? Там, кажется, не быть BaseStream.Abort () или подобным.

Спасибо

Ответы [ 2 ]

1 голос
/ 23 июля 2009

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

object p = _port.BaseStream.GetType().GetField("_handle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField).GetValue(_port.BaseStream);
IntPtr hFile = (IntPtr)p.GetType().GetField("handle", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField).GetValue(p);

Где _port - открытый SerialPort. Затем я закрываю файл следующим образом

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool CloseHandle(IntPtr hFile);
CloseHandle(hFile);

Возможно, есть лучший способ, вызвав один из закрытых методов в BaseStream, но это один из способов:)


0 голосов
/ 14 июля 2009

Я также думаю, что вы не можете отменить операцию, если Stream.Close() не сработает. EndWrite() блоков по конструкции, последовательность BeginWrite() и EndWrite() в одном и том же потоке идентична вызову синхронной функции.

На самом деле, возможно, что для вашей операции даже не запущен поток. Операция может использовать внутренние порты завершения ввода-вывода и запускать обратный вызов только в потоке потоков. (Прошло некоторое время с тех пор, как я изучал эти вещи)

Но то, что вы можете сделать, это «покинуть» поток, установить флаг в вашем коде, и, когда приходит обратный вызов, просто закройте поток, если флаг установлен. Не забудьте поставить lock вокруг флага или сделать его volatile

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