private void buildApplicationCacheMultiThread()
        {
            try
            {
                DateTime globalNow = DateTime.Now;
                this.storage.OpenConnection();
                this.collectPermissionData();
                List<ItemCheckAccessResult> results = new List<ItemCheckAccessResult>();
                IAzManSid sid = this.windowsIdentity != null ? new SqlAzManSID(this.windowsIdentity.User) : this.dbUser.CustomSid;
                List<ManualResetEvent> waitHandles = new List<ManualResetEvent>();
                Hashtable allResult = new Hashtable();
                int index = 0;
                Exception lastException = null;

                foreach (String itemname in this.items)
                {
                    var drAuthorization = this.dtAuthorizations.Where(t => t.ItemName == itemname).FirstOrDefault();
                    if (drAuthorization == null)
                        drAuthorization = new BuildUserPermissionCacheResult2()
                        {
                            ItemName = itemname,
                            ValidFrom = null,
                            ValidTo = null
                        };
                    //string itemName = drAuthorization.ItemName;

                    ManualResetEvent waitHandle = new ManualResetEvent(false);
                    waitHandles.Add(waitHandle);
                    //New Thread Pool
                    ThreadPool.QueueUserWorkItem(new WaitCallback(
                        delegate(object o)
                        {
                            IAzManStorage clonedStorage = new SqlAzManStorage(((SqlAzManStorage)this.storage).db.Connection.ConnectionString);
                            int localIndex = (int)((object[])o)[0];
                            ManualResetEvent localWaitHandle = (ManualResetEvent)((object[])o)[1];
                            BuildUserPermissionCacheResult2 localAuth = (BuildUserPermissionCacheResult2)((object[])o)[2];
                            DateTime now = (DateTime)((object[])o)[3];
                            string itemName = localAuth.ItemName;
                            try
                            {
                                clonedStorage.OpenConnection();
                                ItemCheckAccessResult result = new ItemCheckAccessResult(itemName);
                                result.ValidFrom = localAuth.ValidFrom.HasValue ? localAuth.ValidFrom.Value : DateTime.MinValue;
                                result.ValidTo = localAuth.ValidTo.HasValue ? localAuth.ValidTo.Value : DateTime.MaxValue;
                                List<KeyValuePair<string, string>> attributes = null;
                                DateTime validFor = localAuth.ValidFrom.HasValue ? localAuth.ValidFrom.Value : now;
                                if (this.windowsIdentity != null)
                                {
                                    if (this.retrieveAttributes)
                                        result.AuthorizationType = clonedStorage.CheckAccess(this.storeName, this.applicationName, itemName, this.windowsIdentity, validFor, false, out attributes, this.contextParameters);
                                    else
                                        result.AuthorizationType = clonedStorage.CheckAccess(this.storeName, this.applicationName, itemName, this.windowsIdentity, validFor, false, this.contextParameters);

                                }
                                else if (this.dbUser != null)
                                {
                                    if (this.retrieveAttributes)
                                        result.AuthorizationType = clonedStorage.CheckAccess(this.storeName, this.applicationName, itemName, this.dbUser, validFor, false, out attributes, this.contextParameters);
                                    else
                                        result.AuthorizationType = clonedStorage.CheckAccess(this.storeName, this.applicationName, itemName, this.dbUser, validFor, false, this.contextParameters);
                                }
                                result.Attributes = attributes;
                                //Thread safety
                                lock (allResult.SyncRoot)
                                {
                                    allResult.Add(localIndex, new object[] { itemName, result });
                                }
                            }
                            catch (Exception ex)
                            {
                                lastException = ex;
                            }
                            finally
                            {
                                clonedStorage.CloseConnection();
                                localWaitHandle.Set();
                            }
                        }), new object[] { index, waitHandle, drAuthorization, globalNow });
                    index++;
                }
                if (lastException != null)
                    throw lastException;
                int count = index;
                //Wait for all threads: http://www.devnewsgroups.net/group/microsoft.public.dotnet.framework/topic28609.aspx
                if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
                {
                    // WaitAll for multiple handles on an STA thread is not supported.
                    // ...so wait on each handle individually.
                    foreach (ManualResetEvent myWaitHandle in waitHandles)
                    {
                        myWaitHandle.WaitOne();
                    }
                }
                else
                {
                    WaitHandle.WaitAll(waitHandles.ToArray());
                }
                //Extends all results
                index = 0;
                for (int i = 0; i < count; i++)
                {
                    object[] values = (object[])allResult[index++];
                    string itemName = (string)((object[])values)[0];
                    ItemCheckAccessResult result = (ItemCheckAccessResult)((object[])values)[1];
                    results.Add(result);
                    this.extendResultToMembers(itemName, result, results);
                }
                this.checkAccessTimeSlice = results.ToArray();
            }
            finally
            {
                this.storage.CloseConnection();
            }
        }
        private void buildApplicationCache()
        {
            try
            {
                DateTime now = DateTime.Now;
                this.storage.OpenConnection();
                this.collectPermissionData();
                List<ItemCheckAccessResult> results = new List<ItemCheckAccessResult>();
                IAzManSid sid = this.windowsIdentity!=null ? new SqlAzManSID(this.windowsIdentity.User) : this.dbUser.CustomSid;
                int index = 0;
                //foreach (var drAuthorization in this.dtAuthorizations)
                foreach (String itemName in this.items)
                {
                    var drAuthorization = this.dtAuthorizations.Where(t => t.ItemName == itemName).FirstOrDefault();
                    if (drAuthorization == null)
                        drAuthorization = new BuildUserPermissionCacheResult2()
                        {
                            ItemName = itemName,
                            ValidFrom = null,
                            ValidTo = null
                        };
                    //string itemName = drAuthorization.ItemName;
                    ItemCheckAccessResult result = new ItemCheckAccessResult(itemName);
                    result.ValidFrom = drAuthorization.ValidFrom.HasValue ? drAuthorization.ValidFrom.Value : DateTime.MinValue;
                    result.ValidTo = drAuthorization.ValidTo.HasValue ? drAuthorization.ValidTo.Value : DateTime.MaxValue;
                    List<KeyValuePair<string, string>> attributes = null;
                    DateTime validFor = DateTime.Now;
                    if (drAuthorization.ValidFrom.HasValue)
                    {
                        validFor = drAuthorization.ValidFrom.Value;
                    }
                    else if (drAuthorization.ValidTo.HasValue)
                    {
                        validFor = drAuthorization.ValidTo.Value;
                    }
                    else
                    {
                        var mindt = (from t in this.dtAuthorizations
                                          where t.ValidFrom.HasValue
                                          select t.ValidFrom).Min();
                        if (mindt.HasValue && mindt.Value!=DateTime.MinValue)
                        {
                            validFor = mindt.Value.AddSeconds(-1);
                        }
                        else
                        {
                            var maxdt = (from t in this.dtAuthorizations
                                              where t.ValidTo.HasValue
                                              select t.ValidTo).Max();
                            if (maxdt.HasValue && maxdt.Value != DateTime.MaxValue)
                            {
                                validFor = maxdt.Value.AddSeconds(1);
                            }
                        }
                    }

                    if (this.windowsIdentity != null)
                    {
                        if (this.retrieveAttributes)
                            result.AuthorizationType = this.storage.CheckAccess(this.storeName, this.applicationName, itemName, this.windowsIdentity, validFor, false, out attributes, this.contextParameters);
                        else
                            result.AuthorizationType = this.storage.CheckAccess(this.storeName, this.applicationName, itemName, this.windowsIdentity, validFor, false, this.contextParameters);
                    }
                    else if (this.dbUser != null)
                    {
                        if (this.retrieveAttributes)
                            result.AuthorizationType = this.storage.CheckAccess(this.storeName, this.applicationName, itemName, this.dbUser, validFor, false, out attributes, this.contextParameters);
                        else
                            result.AuthorizationType = this.storage.CheckAccess(this.storeName, this.applicationName, itemName, this.dbUser, validFor, false, this.contextParameters);
                    }
                    result.Attributes = attributes;
                    results.Add(result);
                    this.extendResultToMembers(itemName, result, results);
                    index++;
                }
                this.checkAccessTimeSlice = results.ToArray();
            }
            finally
            {
                this.storage.CloseConnection();
            }
        }