public AsyncRequestStateFileCopy(AsyncFileCopyBean bean)
        { // constructor
            int i = bean.ThreadId;

            BUFFER_SIZE  = bean.BUFFER_SIZE;
            BUFFERS      = bean.BUFFERS;
            bufferOffset = i * BUFFER_SIZE;           // offset in file where buffer reads/writes
            ReadLaunched = new AutoResetEvent(false); // semaphore says reading (not writing)
            Buffer       = new byte[BUFFER_SIZE];     // allocates the buffer
        }
 public void WriteCompleteCallback(IAsyncResult ar)
 {
     lock (WriteCountMutex)
     {                                                                // protect the shared variables
         AsyncFileCopyBean bean = ar.AsyncState as AsyncFileCopyBean; // get request index
         int i = bean.ThreadId;
         bean.Target.EndWrite(ar);                                    // mark the write complete
         bean.BytesWritten += BUFFER_SIZE;                            // advance bytes written
         this.bufferOffset += BUFFERS * BUFFER_SIZE;                  // stride to next slot
         if (this.bufferOffset < bean.TotalBytes)
         {                                                            // if not all read, issue next read
             bean.Source.Position = this.bufferOffset;                // issue read at that offset
             this.ReadAsyncResult = bean.Source.BeginRead(this.Buffer, 0, BUFFER_SIZE, null, i);
             this.ReadLaunched.Set();
         }
     }
 }