Моя цель - создать приложение, способное взаимодействовать с USB HID-устройствами.Основной поток (UI) создает соответствующий дескриптор.
this.handle =
Win32.CreateFile(
devicePath,
Win32.GENERIC_READ | Win32.GENERIC_WRITE,
0,
IntPtr.Zero,
Win32.OPEN_EXISTING,
Win32.FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
После этого запускается два потока.Первое - это непрерывное чтение данных с устройства.Если доступных данных нет, они блокируются.Он использует перекрывающееся чтение.Дескриптор может быть передан объекту FileStream, но я должен использовать вызовы P / Invoke.Моя реализация основана на нескольких библиотеках HID.Таким образом, поток выполняет следующий цикл:
while (true)
{
var overlapped = new Win32.Overlapped();
overlapped.Offset = 0;
overlapped.OffsetHigh = 0;
overlapped.Event = this.readEvent;
var readResult =
Win32.ReadFile(
this.handle,
buffer,
(uint)this.InputReportLength,
IntPtr.Zero,
ref overlapped);
if (readResult == 0)
{
int errorCode = Marshal.GetLastWin32Error();
// Overlapped operation is running => 0x3e5
if (errorCode != 0x3e5)
{
break;
}
}
var result = Win32.WaitForSingleObject(overlapped.Event, Win32.WAIT_INFINITE);
if (result != Win32.WAIT_OBJECT_0 || this.handle == IntPtr.Zero)
{
// Handle is cleared
break;
}
uint bytesRead = 0;
Win32.GetOverlappedResult(this.handle, ref overlapped, out bytesRead, false);
if (bytesRead > 0)
{
byte[] report = new byte[this.InputReportLength];
Array.Copy(buffer, report, Math.Min(bytesRead, report.Length));
// Report data
OnDataReceived(report);
}
}
Второй поток получает команды из параллельной очереди, собирает их в двоичный файл, а затем вызывает следующий метод, который записывает данные на устройство.
IntPtr writeEvent = Win32.CreateEvent(IntPtr.Zero, false, true, Guid.NewGuid().ToString());
var overlapped = new Win32.Overlapped();
overlapped.Offset = 0;
overlapped.OffsetHigh = 0;
overlapped.Event = writeEvent;
int writeResult =
Win32.WriteFile(
this.handle, buffer,
(uint)buffer.Length,
IntPtr.Zero,
ref overlapped);
if (writeResult == 0)
{
int errorCode = Marshal.GetLastWin32Error();
// Overlapped operation is running => 0x3e5
if (errorCode != 0x3e5)
{
throw new IOException(string.Format("Cannot write device ({0})", errorCode));
}
}
var result = Win32.WaitForSingleObject(writeEvent, Win32.WAIT_INFINITE);
Win32.CloseHandle(writeEvent);
if (result != Win32.WAIT_OBJECT_0)
{
throw new IOException("Failed to write");
}
Приложение получает данные, правильно отправленные устройством.Программа просто работает без сбоев. НО если приложение отправляет данные на устройство (помещая объекты команд в указанную очередь), все приложения аварийно завершают работу самопроизвольно .Авария происходит неопределенным образом.В чем причина этого?Моя идея заключается в том, что это вызвано одновременным доступом.Однако одновременное использование объекта FileStream (путем передачи ему дескриптора) не приводит к такому сбою.