Пример #1
0
        private IAsyncResult BeginReadWrite(bool isRead, byte[] buffer, int offset, int count, AsyncCallback callback, object state)
        {
            // To avoid a race with a stream's position pointer & generating race
            // conditions with internal buffer indexes in our own streams that
            // don't natively support async IO operations when there are multiple
            // async requests outstanding, we block the calling thread until
            // the active one completes.
            SemaphoreSlim sem = EnsureAsyncActiveSemaphoreInitialized();

            sem.Wait();
            Debug.Assert(_activeReadWriteTask == null);

            // Create the task to asynchronously run the read or write.  Even though Task implements IAsyncResult,
            // we wrap it in a special IAsyncResult object that stores all of the state for the operation
            // and that we can pass around as a state parameter to all of our delegates.  Even though this
            // is an allocation, this allows us to avoid any closures or non-statically cached delegates
            // for both the Task and its continuation, saving more allocations.
            var  asyncResult = new StreamReadWriteAsyncResult(_stream, buffer, offset, count, callback, state);
            Task t;

            if (isRead)
            {
                t = new Task <int>(obj =>
                {
                    var ar = (StreamReadWriteAsyncResult)obj;
                    return(ar._stream.Read(ar._buffer, ar._offset, ar._count));
                }, asyncResult, CancellationToken.None, TaskCreationOptions.DenyChildAttach);
            }
            else
            {
                t = new Task(obj =>
                {
                    var ar = (StreamReadWriteAsyncResult)obj;
                    ar._stream.Write(ar._buffer, ar._offset, ar._count);
                }, asyncResult, CancellationToken.None, TaskCreationOptions.DenyChildAttach);
            }

            asyncResult._task = t; // this doesn't happen in the async result's ctor because the Task needs to reference the AR, and vice versa

            if (callback != null)
            {
                t.ContinueWith((_, obj) =>
                {
                    var ar = (StreamReadWriteAsyncResult)obj;
                    ar._callback(ar);
                }, asyncResult, CancellationToken.None, TaskContinuationOptions.DenyChildAttach | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
            }

            _activeReadWriteTask = t;
            t.Start(TaskScheduler.Default);

            return(asyncResult);
        }
Пример #2
0
        private IAsyncResult BeginReadWrite(bool isRead, byte[] buffer, int offset, int count, AsyncCallback callback, object state)
        {
            // To avoid a race with a stream's position pointer & generating race 
            // conditions with internal buffer indexes in our own streams that 
            // don't natively support async IO operations when there are multiple 
            // async requests outstanding, we block the calling thread until 
            // the active one completes.
            SemaphoreSlim sem = EnsureAsyncActiveSemaphoreInitialized();
            sem.Wait();
            Debug.Assert(_activeReadWriteTask == null);

            // Create the task to asynchronously run the read or write.  Even though Task implements IAsyncResult,
            // we wrap it in a special IAsyncResult object that stores all of the state for the operation
            // and that we can pass around as a state parameter to all of our delegates.  Even though this
            // is an allocation, this allows us to avoid any closures or non-statically cached delegates
            // for both the Task and its continuation, saving more allocations.
            var asyncResult = new StreamReadWriteAsyncResult(_stream, buffer, offset, count, callback, state);
            Task t;
            if (isRead)
            {
                t = new Task<int>(obj =>
                {
                    var ar = (StreamReadWriteAsyncResult)obj;
                    return ar._stream.Read(ar._buffer, ar._offset, ar._count);
                }, asyncResult, CancellationToken.None, TaskCreationOptions.DenyChildAttach);
            }
            else
            {
                t = new Task(obj =>
                {
                    var ar = (StreamReadWriteAsyncResult)obj;
                    ar._stream.Write(ar._buffer, ar._offset, ar._count);
                }, asyncResult, CancellationToken.None, TaskCreationOptions.DenyChildAttach);
            }

            asyncResult._task = t; // this doesn't happen in the async result's ctor because the Task needs to reference the AR, and vice versa

            if (callback != null)
            {
                t.ContinueWith((_, obj) =>
                {
                    var ar = (StreamReadWriteAsyncResult)obj;
                    ar._callback(ar);
                }, asyncResult, CancellationToken.None, TaskContinuationOptions.DenyChildAttach | TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
            }

            _activeReadWriteTask = t;
            t.Start(TaskScheduler.Default);

            return asyncResult;
        }