PageRenderTime 36ms CodeModel.GetById 15ms app.highlight 13ms RepoModel.GetById 2ms app.codeStats 0ms

/V4/MVVM RI/MVVM.Questionnaires/Services/AsyncResult.cs

#
C# | 157 lines | 120 code | 21 blank | 16 comment | 15 complexity | e33053a5e0a1689591b9c2236eb2eae2 MD5 | raw file
  1//===================================================================================
  2// Microsoft patterns & practices
  3// Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4//===================================================================================
  5// Copyright (c) Microsoft Corporation.  All rights reserved.
  6// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9// FITNESS FOR A PARTICULAR PURPOSE.
 10//===================================================================================
 11// The example companies, organizations, products, domain names,
 12// e-mail addresses, logos, people, places, and events depicted
 13// herein are fictitious.  No association with any real company,
 14// organization, product, domain name, email address, logo, person,
 15// places, or events is intended or should be inferred.
 16//===================================================================================
 17using System;
 18using System.Diagnostics.CodeAnalysis;
 19using System.Threading;
 20
 21namespace MVVM.Questionnaires.Services
 22{
 23    [SuppressMessage("Microsoft.Design", "CA1001",
 24        Justification = "Calling the End method, which is part of the contract of using an IAsyncResult, releases the IDisposable.")]
 25    public class AsyncResult<T> : IAsyncResult
 26    {
 27        private readonly object lockObject;
 28        private readonly AsyncCallback asyncCallback;
 29        private readonly object asyncState;
 30        private ManualResetEvent waitHandle;
 31        private T result;
 32        private Exception exception;
 33        private bool isCompleted;
 34        private bool completedSynchronously;
 35        private bool endCalled;
 36
 37        public AsyncResult(AsyncCallback asyncCallback, object asyncState)
 38        {
 39            this.lockObject = new object();
 40            this.asyncCallback = asyncCallback;
 41            this.asyncState = asyncState;
 42        }
 43
 44        public object AsyncState
 45        {
 46            get { return this.asyncState; }
 47        }
 48
 49        public WaitHandle AsyncWaitHandle
 50        {
 51            get
 52            {
 53                lock (this.lockObject)
 54                {
 55                    if (this.waitHandle == null)
 56                    {
 57                        this.waitHandle = new ManualResetEvent(this.IsCompleted);
 58                    }
 59                }
 60
 61                return this.waitHandle;
 62            }
 63        }
 64
 65        public bool CompletedSynchronously
 66        {
 67            get { return this.completedSynchronously; }
 68        }
 69
 70        public bool IsCompleted
 71        {
 72            get { return this.isCompleted; }
 73        }
 74
 75        public T Result
 76        {
 77            get { return this.result; }
 78        }
 79
 80        [SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes",
 81            Justification = "Entry point to be used to implement End* methods.")]
 82        public static AsyncResult<T> End(IAsyncResult asyncResult)
 83        {
 84            var localResult = asyncResult as AsyncResult<T>;
 85            if (localResult == null)
 86            {
 87                throw new ArgumentNullException("asyncResult");
 88            }
 89
 90            lock (localResult.lockObject)
 91            {
 92                if (localResult.endCalled)
 93                {
 94                    throw new InvalidOperationException("End method already called");
 95                }
 96
 97                localResult.endCalled = true;
 98            }
 99
100            if (!localResult.IsCompleted)
101            {
102                localResult.AsyncWaitHandle.WaitOne();
103            }
104
105            if (localResult.waitHandle != null)
106            {
107                localResult.waitHandle.Close();
108            }
109
110            if (localResult.exception != null)
111            {
112                throw localResult.exception;
113            }
114
115            return localResult;
116        }
117
118        public void SetComplete(T result, bool completedSynchronously)
119        {
120            this.result = result;
121
122            this.DoSetComplete(completedSynchronously);
123        }
124
125        public void SetComplete(Exception e, bool completedSynchronously)
126        {
127            this.exception = e;
128
129            this.DoSetComplete(completedSynchronously);
130        }
131
132        private void DoSetComplete(bool completedSynchronously)
133        {
134            if (completedSynchronously)
135            {
136                this.completedSynchronously = true;
137                this.isCompleted = true;
138            }
139            else
140            {
141                lock (this.lockObject)
142                {
143                    this.isCompleted = true;
144                    if (this.waitHandle != null)
145                    {
146                        this.waitHandle.Set();
147                    }
148                }
149            }
150
151            if (this.asyncCallback != null)
152            {
153                this.asyncCallback(this);
154            }
155        }
156    }
157}