/// <summary> /// Spin wait until data is avaiable or timed out. /// </summary> /// <param name="source">The source stream to check.</param> /// <param name="timeoutClock">The time to check.</param> private static void SpinWaitHandler(System.IO.Stream source, Custom.TimeoutClock timeoutClock) { bool exitIndicator = false; // Create the tasks. Task[] tasks = new Task[1]; // Poller task. Task poller = Task.Factory.StartNew(() => { // Create a new spin wait. SpinWait sw = new SpinWait(); // Action to perform. while (!exitIndicator) { // The NextSpinWillYield property returns true if // calling sw.SpinOnce() will result in yielding the // processor instead of simply spinning. if (sw.NextSpinWillYield) { if (timeoutClock.IsComplete() || source.Length > 0) { exitIndicator = true; } } sw.SpinOnce(); } }); // Assign the listener task. tasks[0] = poller; // Wait for all tasks to complete. Task.WaitAll(tasks); // For each task. foreach (Task item in tasks) { try { // Release the resources. item.Dispose(); } catch { } } tasks = null; }
/// <summary> /// Read the bytes from the stream. /// </summary> /// <param name="source">The current stream.</param> /// <param name="length">The number of bytes to read.</param> /// <param name="completed">True if completed and did not timeout; else false.</param> /// <param name="timeout">The maximum time in milliseconds to wait for the end of the header data; -1 wait indefinitely.</param> /// <returns>The bytes read.</returns> public static byte[] ReadBytesTimer(this System.IO.Stream source, int length, out bool completed, long timeout = -1) { int readBytes = 0; long totalBytesRead = 0; int bufferLength = length; byte[] buffer = new byte[bufferLength]; // If completed. completed = true; using (MemoryStream destination = new MemoryStream()) { // Only if data needs to be found. if (length > 0) { // Start a new timeout clock. Custom.TimeoutClock timeoutClock = new Custom.TimeoutClock((int)timeout); // Read all the data in the source stream and // write the data to the destination stream. do { // Determine the number of bytes to read // from the byteLength and buffer_size. // Can not read more then byteLength. if (length <= bufferLength) { // Look for current total bytes read and number left. long left = length - totalBytesRead; if (left <= bufferLength) { bufferLength = (int)left; } else { bufferLength = (int)length; } } else { // Look for current total bytes read and number left. long left = length - totalBytesRead; if (left <= bufferLength) { bufferLength = (int)left; } } // Read the data and then write the data. readBytes = source.Read(buffer, 0, bufferLength); // If data exists. if (readBytes > 0) { // Each time data is read reset the timeout. timeoutClock.Reset(); totalBytesRead += readBytes; destination.Write(buffer, 0, readBytes); } else { SpinWaitHandler(source, timeoutClock); } // If the timeout has been reached then // break from the loop. if (timeoutClock.IsComplete()) { completed = false; break; } }while (totalBytesRead < length); } // Return the data as bytes. destination.Close(); return(destination.ToArray()); } }