private static extern bool ReadFile( SafeFileHandle hFile, SafeGlobalMemoryPtr lpBuffer, //IntPtr int nNumberOfBytesToRead, ref int lpNumberOfBytesRead, IntPtr lpOverlapped //ref LPOVERLAPPED );
//【スレッド】インタラプト転送(IN)を受信する /* * ReadFile()は受信完了するまでスレッドをブロックする * ・reqThreadStop=trueとなってもReadFile()が完了しない限りwhile()を抜けることはできない。 * 途切れることなくデータを受信するような動作をしているなら問題ないが、 * いつ来るか分からない(来ないかもしれない)データを待ち続けるような動作をしているなら、 * いつまでもwhile()を抜けることができないということ。 * ・そのような待ち続けの動作があることを考慮すると、タイムアウトを設定するのは適切と言えない。 * タイムアウト発生でReadFile()を終了した瞬間に、運悪くデータが送信されるかもしれないので。 * 例えすぐに次のReadFile()を開始しようとも、それを受信することはできない。 * * ReadFile()がアンマネージコードであるためか、Abort()してもfinally{}を実行せずにスレッドが破棄される。 * すると、Marshal.AllocHGlobal()で確保したメモリが開放できない。 * 解決策:確保したメモリのIntPtrを、SafeFileHandle同様の仕組みで扱えるようにする。 * →SafeFileHandle同様の仕組みの中でメモリを確保する。 */ /* コールバック関数への戻り値 * 成功:レポートIDを含むInputReport(byte配列) * 失敗:成功時より長さが足りないか、長さ0のbyte配列(nullではない) */ private static void ReadThread(object oParam) { TThParam thParam = (TThParam)oParam; //内容は妥当であるものとする SafeFileHandle hHidDev = DeviceAccess.Open(thParam.devicePath, CFF.GENERIC_READ); if (hHidDev.IsInvalid) { hHidDev.Close(); return; } int bufSize = thParam.reportLength; SafeGlobalMemoryPtr pGlobalBuf = new SafeGlobalMemoryPtr(bufSize); if (pGlobalBuf.IsInvalid) { pGlobalBuf.Close(); hHidDev.Close(); return; } try { int readLength = 0; byte[] rcvBytes; while (0 < bufSize) //無限ループする条件なら何でもよい { rcvBytes = null; if (DeviceAccess.ReadFile(hHidDev, pGlobalBuf, bufSize, ref readLength)) { rcvBytes = new byte[readLength]; if (0 < readLength) { Marshal.Copy(pGlobalBuf.DangerousGetHandle(), rcvBytes, 0, readLength); } thParam.userMethod(rcvBytes); } /* debug * for (int i = 0; rcvBytes != null && i < rcvBytes.Length; i++) * Console.Write("{0:X2} ", rcvBytes[i]); * Console.WriteLine(); * //*/ } } catch { } pGlobalBuf.Close(); hHidDev.Close(); }
//デバイスから読み込む public static bool ReadFile(SafeFileHandle hFile, SafeGlobalMemoryPtr lpBuffer, int nNumberOfBytesToRead, ref int lpNumberOfBytesRead) { bool isOK = ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, ref lpNumberOfBytesRead, IntPtr.Zero); return(isOK); }