Пример #1
0
        // 清除已经失效的 PageItem
        // parameters:
        //      delta   闲置多少时间以上才清理
        public void Clean(bool bLock,
                          TimeSpan delta,
                          Delegate_deleteFile procDeleteFile,
                          CancellationToken token)
        {
            List <string>   keys  = new List <string>();
            List <PageItem> items = new List <PageItem>();

            if (bLock)
            {
                _lock.EnterReadLock();
            }
            try
            {
                DateTime now = DateTime.Now;
                foreach (string key in _pageTable.Keys)
                {
                    token.ThrowIfCancellationRequested();

                    PageItem item = _pageTable[key];
                    if (item.State == "OK" &&
                        now - item.LastUse > delta)
                    {
                        keys.Add(key);
                        items.Add(item);
                    }
                }
            }
            finally
            {
                if (bLock)
                {
                    _lock.ExitReadLock();
                }
            }

            if (keys.Count > 0)
            {
                if (bLock)
                {
                    _lock.EnterWriteLock();
                }
                try
                {
                    foreach (string key in keys)
                    {
                        token.ThrowIfCancellationRequested();

                        _pageTable.Remove(key);
                    }
                }
                finally
                {
                    if (bLock)
                    {
                        _lock.ExitWriteLock();
                    }
                }

                foreach (PageItem item in items)
                {
                    token.ThrowIfCancellationRequested();

                    if (procDeleteFile != null)
                    {
                        procDeleteFile(item.FilePath);
                    }
                    else
                    {
                        item.Delete();
                    }
                }
            }
        }
Пример #2
0
        // 准备一个 PageItem 对象。如果在 _pageTable 中已经存在了,则直接利用它;如果没有,则新创建一个
        // 但要处理好一个文件,新创建好的 PageItem 对象,其物理文件还没有来得及创建,如果这段时间又有另一个线程并发获得使用了这个对象,则会发生冲突。解决办法是,规定只返回准备好物理文件的 PageItem 对象。这样可能会出现两个线程都同时在创建相似属性的 PageItem 对象的可能
        public PageItem GetPage(string object_recpath,
                                int page_no,
                                int dpi,
                                string format,
                                Delegate_prepareFile procPrepareFile,
                                Delegate_deleteFile procDeleteFile,
                                CancellationToken token)
        {
            string   key     = PageItem.MakeKey(object_recpath, page_no, dpi, format);
            PageItem item    = null;
            bool     bNew    = false; // 是否新创建了 PageItem 对象
            bool     bFreely = false; // 是否为独立的 Page Item 对象。独立的 PageItem 对象不被集合管理

            _lock.EnterWriteLock();
            try
            {
                if (_pageTable.TryGetValue(key, out item) == true &&
                    item.State == "OK")
                {
                    return(item);
                }

                if (item == null)
                {
                    if (_pageTable.Count >= MAX_ITEMS)
                    {
                        // 紧急清理一次
                        Clean(false, TimeSpan.FromMilliseconds(0), procDeleteFile, token);
                    }

                    item = new PageItem
                    {
                        RecordPath = object_recpath,
                        Page       = page_no,
                        DPI        = dpi,
                        Format     = format,
                        State      = "Lock"
                    };

                    if (this._pageTable.Count < MAX_ITEMS)
                    {
                        _pageTable.Add(key, item);
                    }
                    else
                    {
                        bFreely = true;
                    }
                    bNew = true;
                }
                else
                {
                    // 等待状态变成 OK
                    bNew = false;
                }
            }
            finally
            {
                _lock.ExitWriteLock();
            }

            if (bNew == true)
            {
                try
                {
                    // 创建物理文件
                    var ret = procPrepareFile();
                    item.FilePath  = ret.Item1;
                    item.TotalPage = ret.Item2;
                    if (bFreely)
                    {
                        item.State = "Freely";
                    }
                    else
                    {
                        item.State = "OK";
                    }
                    // Thread.Sleep(10000);
                }
                catch
                {
                    _lock.EnterWriteLock();
                    try
                    {
                        _pageTable.Remove(key);
                    }
                    finally
                    {
                        _lock.ExitWriteLock();
                    }

                    throw;
                }
            }
            else
            {
                TimeSpan timeout = TimeSpan.FromSeconds(10);
                DateTime start   = DateTime.Now;
                // 等待状态变为 OK
                while (true)
                {
                    Thread.Sleep(100);
                    if (item.State == "OK")
                    {
                        break;
                    }
                    // TODO: 超时要抛出异常
                    if (DateTime.Now - start >= timeout)
                    {
                        throw new TimeoutException("PageItem 对象被其它请求占用。请稍后重试");
                    }
                }
            }
            return(item);
        }