示例#1
0
        private void WriteMain(byte[] buf, int offset, int length)
        {
            byte[] bufToWrite;

            while (length > 0)
            {
                if (offset != 0)
                {
                    bufToWrite = new byte[length];
                    Buffer.BlockCopy(buf, offset, bufToWrite, 0, length);
                }
                else
                {
                    bufToWrite = buf;
                }

                int              wroteLength             = 0;
                GCHandle         wroteLengthPinned       = GCHandle.Alloc(wroteLength, GCHandleType.Pinned);
                int              transferredLength       = 0;
                GCHandle         transferredLengthPinned = GCHandle.Alloc(transferredLength, GCHandleType.Pinned);
                NativeOverlapped writeOverlapped         = new NativeOverlapped();
                writeOverlapped.EventHandle = _writeOverlappedEvent.SafeWaitHandle.DangerousGetHandle();
                GCHandle writeOverlappedPinned = GCHandle.Alloc(writeOverlapped, GCHandleType.Pinned);
                GCHandle bufToWritePinned      = GCHandle.Alloc(bufToWrite, GCHandleType.Pinned);

                // Note:
                //  GCHandle.Alloc(<struct>, GCHandleType.Pinned) makes a GCHandle for `Boxed' struct object.
                //  So if you want to read a value of the struct, you have to read it from `Boxed' struct object
                //  which is returned by GCHandle.Target.

                try {
                    bool success = Win32Serial.WriteFile(
                        _fileHandle,
                        bufToWritePinned.AddrOfPinnedObject(),
                        length,
                        wroteLengthPinned.AddrOfPinnedObject(),
                        writeOverlappedPinned.AddrOfPinnedObject());
                    if (!success)
                    {
                        int lastErr = Marshal.GetLastWin32Error();
                        if (lastErr != Win32.ERROR_IO_PENDING)
                        {
                            throw new IOException("WriteFile failed for " + lastErr);
                        }

                        success = Win32Serial.GetOverlappedResult(
                            _fileHandle,
                            writeOverlappedPinned.AddrOfPinnedObject(),
                            transferredLengthPinned.AddrOfPinnedObject(),
                            true);
                        if (!success)
                        {
                            lastErr = Marshal.GetLastWin32Error();
                            throw new Exception("GetOverlappedResult failed " + lastErr);
                        }
                        wroteLength = (int)transferredLengthPinned.Target;  // copy from pinned `boxed' Int32
                    }
                    else
                    {
                        wroteLength = (int)wroteLengthPinned.Target;    // copy from pinned `boxed' Int32
                    }
                }
                finally {
                    wroteLengthPinned.Free();
                    transferredLengthPinned.Free();
                    writeOverlappedPinned.Free();
                    bufToWritePinned.Free();
                }

                offset += wroteLength;
                length -= wroteLength;
            }
        }
示例#2
0
        private void AsyncEntry()
        {
            const int EV_RXCHAR = 1;

            ManualResetEvent commEventOverlappedEvent = null;
            ManualResetEvent readOverlappedEvent      = null;

            try {
                commEventOverlappedEvent = new ManualResetEvent(false);
                readOverlappedEvent      = new ManualResetEvent(false);

                NativeOverlapped commEventOverlapped = new NativeOverlapped();
                commEventOverlapped.EventHandle = commEventOverlappedEvent.SafeWaitHandle.DangerousGetHandle();

                NativeOverlapped readOverlapped = new NativeOverlapped();
                readOverlapped.EventHandle = readOverlappedEvent.SafeWaitHandle.DangerousGetHandle();

                GCHandle commEventOverlappedPinned = GCHandle.Alloc(commEventOverlapped, GCHandleType.Pinned); // Pin a boxed NativeOverlapped
                GCHandle readOverlappedPinned      = GCHandle.Alloc(readOverlapped, GCHandleType.Pinned);      // Pin a boxed NativeOverlapped
                int      commFlags               = 0;
                GCHandle commFlagsPinned         = GCHandle.Alloc(commFlags, GCHandleType.Pinned);             // Pin a boxed Int32
                int      readLength              = 0;
                GCHandle readLengthPinned        = GCHandle.Alloc(readLength, GCHandleType.Pinned);            // Pin a boxed Int32
                int      transferredLength       = 0;
                GCHandle transferredLengthPinned = GCHandle.Alloc(transferredLength, GCHandleType.Pinned);     // Pin a boxed Int32

                byte[]   buf       = new byte[128];
                GCHandle bufPinned = GCHandle.Alloc(buf, GCHandleType.Pinned);

                // Note:
                //  GCHandle.Alloc(<struct>, GCHandleType.Pinned) makes a GCHandle for `Boxed' struct object.
                //  So if you want to read a value of the struct, you have to read it from `Boxed' struct object
                //  which is returned by GCHandle.Target.

                try {
                    bool success = false;

                    success = Win32Serial.ClearCommError(_fileHandle, IntPtr.Zero, IntPtr.Zero);
                    if (!success)
                    {
                        throw new Exception("ClearCommError failed " + Marshal.GetLastWin32Error());
                    }
                    //このSetCommMaskを実行しないとWaitCommEventが失敗してしまう
                    success = Win32Serial.SetCommMask(_fileHandle, 0);
                    if (!success)
                    {
                        throw new Exception("SetCommMask failed " + Marshal.GetLastWin32Error());
                    }
                    success = Win32Serial.SetCommMask(_fileHandle, EV_RXCHAR);
                    if (!success)
                    {
                        throw new Exception("SetCommMask failed " + Marshal.GetLastWin32Error());
                    }

                    while (true)
                    {
                        commFlags = 0;
                        commFlagsPinned.Target           = commFlags;           // Pin a new boxed Int32
                        transferredLength                = 0;
                        transferredLengthPinned.Target   = transferredLength;   // Pin a new boxed Int32
                        commEventOverlappedPinned.Target = commEventOverlapped; // Pin a new boxed NativeOverlapped

                        success = Win32Serial.WaitCommEvent(
                            _fileHandle,
                            commFlagsPinned.AddrOfPinnedObject(),
                            commEventOverlappedPinned.AddrOfPinnedObject());
                        if (!success)
                        {
                            int lastErr = Marshal.GetLastWin32Error();
                            if (lastErr == Win32.ERROR_INVALID_HANDLE)
                            {
                                goto CLOSED;  // closed in another thread ?
                            }
                            if (lastErr != Win32.ERROR_IO_PENDING)
                            {
                                throw new Exception("WaitCommEvent failed " + lastErr);
                            }

                            success = Win32Serial.GetOverlappedResult(
                                _fileHandle,
                                commEventOverlappedPinned.AddrOfPinnedObject(),
                                transferredLengthPinned.AddrOfPinnedObject(),
                                true);
                            if (!success)
                            {
                                lastErr = Marshal.GetLastWin32Error();
                                if (lastErr == Win32.ERROR_INVALID_HANDLE || lastErr == Win32.ERROR_OPERATION_ABORTED)
                                {
                                    goto CLOSED;  // closed in another thread ?
                                }
                                throw new Exception("GetOverlappedResult failed " + lastErr);
                            }
                        }

                        if ((int)commFlagsPinned.Target != EV_RXCHAR)
                        {
                            goto CLOSED;
                        }

                        while (true)
                        {
                            readLength = 0;
                            readLengthPinned.Target        = readLength;        // Pin a new boxed Int32
                            transferredLength              = 0;
                            transferredLengthPinned.Target = transferredLength; // Pin a new boxed Int32
                            readOverlappedPinned.Target    = readOverlapped;    // Pin a new boxed NativeOverlapped

                            success = Win32Serial.ReadFile(
                                _fileHandle,
                                bufPinned.AddrOfPinnedObject(),
                                buf.Length,
                                readLengthPinned.AddrOfPinnedObject(),
                                readOverlappedPinned.AddrOfPinnedObject());
                            if (!success)
                            {
                                int lastErr = Marshal.GetLastWin32Error();
                                if (lastErr == Win32.ERROR_INVALID_HANDLE)
                                {
                                    goto CLOSED;  // closed in another thread ?
                                }
                                if (lastErr != Win32.ERROR_IO_PENDING)
                                {
                                    throw new Exception("ReadFile failed " + lastErr);
                                }

                                success = Win32Serial.GetOverlappedResult(
                                    _fileHandle,
                                    readOverlappedPinned.AddrOfPinnedObject(),
                                    transferredLengthPinned.AddrOfPinnedObject(),
                                    true);
                                if (!success)
                                {
                                    lastErr = Marshal.GetLastWin32Error();
                                    if (lastErr == Win32.ERROR_INVALID_HANDLE || lastErr == Win32.ERROR_OPERATION_ABORTED)
                                    {
                                        goto CLOSED;  // closed in another thread ?
                                    }
                                    throw new Exception("GetOverlappedResult failed " + lastErr);
                                }
                                readLength = (int)transferredLengthPinned.Target;   // copy from pinned `boxed' Int32
                            }
                            else
                            {
                                readLength = (int)readLengthPinned.Target;  // copy from pinned `boxed' Int32
                            }

                            if (readLength <= 0)
                            {
                                break;
                            }

                            _dataFragment.Set(buf, 0, readLength);
                            _callback.OnReception(_dataFragment);
                        }
                    }
                }
                finally {
                    commEventOverlappedPinned.Free();
                    readOverlappedPinned.Free();
                    commFlagsPinned.Free();
                    readLengthPinned.Free();
                    transferredLengthPinned.Free();
                    bufPinned.Free();
                }

CLOSED:
                ;
            }
            catch (Exception ex) {
                if (!_parent.IsClosed)
                {
                    _callback.OnAbnormalTermination(ex.Message);
                }
            }
            finally {
                if (commEventOverlappedEvent != null)
                {
                    commEventOverlappedEvent.Close();
                }
                if (readOverlappedEvent != null)
                {
                    readOverlappedEvent.Close();
                }
            }
        }