Fu

Fu

  • NA
  • 1
  • 0

Asynch I/O issue

May 6 2009 6:04 PM
I was playing with asynchronous file I/O and I noticed a weird behavior. It seems to be tagged on a buffer size being constant. The code below reads a file and copies the contents to another file. Search for line that looks like this iSize += 08;//Make this increment… If you let the iSize be constant the runtime behavior changes a lot. I was thinking that some “buggy” optimization code tries to reuse the data buffer (for same size scenario) and this causes the problem…
using System.IO;
using System.Threading;
...
    class AsynchFileProcess
    {
        private const int BUFF_SIZE = 256;
        private long writeCount = 0;
        private long readCount = 0;
        private FileStream istrm;
        private FileStream ostrm;
        private String outFileName;

        public void ProcessFile(String fileName)
        {
            istrm = new FileStream(fileName, FileMode.Open,
                                    FileAccess.Read, FileShare.Read,
                                    BUFF_SIZE, true);
            FileInfo fi = new FileInfo(fileName);
            String dir = fi.Directory.ToString();
            do
            {
                outFileName = dir + "/" + Guid.NewGuid().ToString();
                fi = new FileInfo(outFileName);
            } while (fi.Exists);

            ostrm = new FileStream(outFileName, FileMode.CreateNew,
                                    FileAccess.Write, FileShare.None,
                                    BUFF_SIZE, true);

            long Length = istrm.Length;
            int iSize = BUFF_SIZE;
            while (Length != istrm.Position)
            {
                iSize += 08;//Make this increment 0 and the executable will hang and run sloooow
                byte[] data = new Byte[iSize];
                istrm.BeginRead(data, 0, data.Length, new AsyncCallback(onReadBuffer), data);
                Interlocked.Increment(ref readCount);
            }

            //wait for all the read operations to complete
            while (0 != Interlocked.CompareExchange(ref readCount, 0, 0))
                Thread.Sleep(250);
            istrm.Close();

            //wait for all the write operations to complete
            while (0 != Interlocked.CompareExchange(ref writeCount, 0, 0))
                Thread.Sleep(250);
            ostrm.Close();
        }

        private void onReadBuffer(IAsyncResult result)
        {
            Byte[] data = (Byte[])result.AsyncState;
            int bytesRead = istrm.EndRead(result);

            Interlocked.Increment(ref writeCount);
            ostrm.BeginWrite(data, 0, bytesRead, new AsyncCallback(onWriteBuffer), null);
            
            Interlocked.Decrement(ref readCount);
            Console.WriteLine("bytesRead={0}   buffersCnt={1}  thread={2}", bytesRead, readCount, Thread.CurrentThread.GetHashCode());
        }

        private void onWriteBuffer(IAsyncResult result)
        {
            ostrm.EndWrite(result);
            Interlocked.Decrement(ref writeCount);
            Console.WriteLine("writeCnt={0}   thread={1}", writeCount, Thread.CurrentThread.GetHashCode());
        }
    }