void ThreadFunc(object context) { Queue <byte[]> receivedData = new Queue <byte[]>(BufferList.Length); while (true) { if (Device.Stopping) { break; } try { PendingBuffers.Peek().Wait(); // Process a large group of received buffers in a batch, if available. int n = 0; try { while (n < BufferList.Length) { QueuedBuffer buf = PendingBuffers.Peek(); if (n == 0 || buf.Ready) { byte[] data = Device.EndReadPipe(buf); PendingBuffers.Dequeue(); if (data != null) { // null is a timeout condition. receivedData.Enqueue(data); } Device.BeginReadPipe(DevicePipeId, buf); // Todo: If this operation fails during normal operation, the buffer is lost from rotation. // Should never happen during normal operation, but should confirm and mitigate if it's possible. PendingBuffers.Enqueue(buf); } n++; } } finally { // Unless we're exiting, ensure we always indicate the data, even if some operation failed. if (!Device.Stopping && receivedData.Count > 0) { lock (this) { foreach (byte[] data in receivedData) { ReceivedData.Enqueue(data); QueuedLength += data.Length; TotalReceived += data.Length; } } ThreadPool.QueueUserWorkItem(RaiseNewData); receivedData.Clear(); } } } catch (Exception ex) { System.Diagnostics.Debug.Print("Should not happen: Exception in background thread. {0}", ex.ToString()); Thread.Sleep(15); } ReceiveTick.Set(); } Stopped = true; }
void ThreadFunc(object context) { int recvBytes; while (true) { if (Device.Stopping) { break; } try { recvBytes = 0; if (PendingBuffers.Count > 0) { PendingBuffers.Peek().Wait(); } // Process a large group of received buffers in a batch, if available. int n = 0; bool shortcut = PendingBuffers.Count > 0; try { lock (RequeuePending) { // Requeue buffers that were drained. while (RequeuePending.Count > 0) { QueuedBuffer buf = RequeuePending.Dequeue(); Device.BeginReadPipe(DevicePipeId, buf); // Todo: If this operation fails during normal operation, the buffer is lost from rotation. // Should never happen during normal operation, but should confirm and mitigate if it's possible. PendingBuffers.Enqueue(buf); } } if (PendingBuffers.Count == 0) { Thread.Sleep(0); } else { lock (BufferLock) { while (n < BufferList.Length && PendingBuffers.Count > 0) { QueuedBuffer buf = PendingBuffers.Peek(); if (shortcut || buf.Ready) { shortcut = false; PendingBuffers.Dequeue(); if (Device.EndReadPipe(buf)) { ReceivedBuffers.Enqueue(buf); recvBytes += buf.CompletedSize; } else { // Timeout condition. Requeue. Device.BeginReadPipe(DevicePipeId, buf); // Todo: If this operation fails during normal operation, the buffer is lost from rotation. // Should never happen during normal operation, but should confirm and mitigate if it's possible. PendingBuffers.Enqueue(buf); } } n++; } } } } finally { // Unless we're exiting, ensure we always indicate the data, even if some operation failed. if (!Device.Stopping && recvBytes > 0) { lock (this) { QueuedLength += recvBytes; TotalReceived += recvBytes; } ThreadNewData.Set(); //ThreadPool.QueueUserWorkItem(RaiseNewData); } } } catch (Exception ex) { System.Diagnostics.Debug.Print("Should not happen: Exception in background thread. {0}", ex.ToString()); Thread.Sleep(15); } ReceiveTick.Set(); } Stopped = true; }