私の目標は、USB HIDデバイスと通信できるアプリケーションを作成することです。メイン(UI)スレッドは、適切なハンドルを作成します。P/Invoke(Win32 API)と並行スレッドとのUSB HID通信
this.handle =
Win32.CreateFile(
devicePath,
Win32.GENERIC_READ | Win32.GENERIC_WRITE,
0,
IntPtr.Zero,
Win32.OPEN_EXISTING,
Win32.FILE_FLAG_OVERLAPPED,
IntPtr.Zero);
この後、2つのスレッドが開始されます。 1つ目は、デバイスからのデータの読み取りを継続することです。利用可能なデータがない場合、ブロックされます。重複した読みを使用します。ハンドルは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");
}
アプリケーションは、デバイスによって正しくプッシュされたデータを受信します。プログラムは何の失敗もなく円滑に実行されます。 BUTアプリケーションが(コマンドオブジェクトを前述のキューに配置することによって)デバイスにデータを送信する場合、アプリケーション全体がクラッシュする自発的に。クラッシュは不確定的なやり方で起こる。これの背後にある理由は何ですか?私の考えは、それが同時アクセスによって引き起こされるということです。しかし、(ハンドルを渡すことによって)FileStreamオブジェクトを同時に使用しても、このようなクラッシュは発生しません。
何も、クラッシュの詳細が重要です。この種のコードは書かないでください.FileStream(SafeFileHandle、FileAccess、int、bool)コンストラクタを使用すれば、CreateFileをピンボケするだけで、.NET以外の方法でも実行できます。 –
@HansPassant Unfortunatelly例外なくアプリケーションがクラッシュするため、クラッシュの詳細を伝えることはできません。 私は** ** P/Invokeを実装する必要があると述べました。誰かがSilverlight 5のFileStreamオブジェクトにハンドルをプッシュする回避策がない限り。 – tamasf