From f3d6eb2556e7739b167f1f4fd79251b1bb660ac8 Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Tue, 9 Apr 2013 15:01:28 +0900 Subject: [PATCH] =?utf8?q?ImageCache=E3=81=AE=E6=8E=92=E4=BB=96=E5=88=B6?= =?utf8?q?=E5=BE=A1=E3=82=92=E6=94=B9=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Monitorクラスを使用して排他制御を行っていた箇所をReaderWriterLockSlimに置き換え --- OpenTween/ImageCache.cs | 65 ++++++++++++++++++++++++--------------- OpenTween/Resources/ChangeLog.txt | 1 + 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/OpenTween/ImageCache.cs b/OpenTween/ImageCache.cs index 5462a816..90192079 100644 --- a/OpenTween/ImageCache.cs +++ b/OpenTween/ImageCache.cs @@ -45,7 +45,7 @@ namespace OpenTween /// /// innerDictionary の排他制御のためのロックオブジェクト /// - private object lockObject = new object(); + private ReaderWriterLockSlim lockObject = new ReaderWriterLockSlim(); /// /// オブジェクトが破棄された否か @@ -54,11 +54,13 @@ namespace OpenTween public ImageCache() { - lock (this.lockObject) + this.lockObject.EnterWriteLock(); + try { this.innerDictionary = new LRUCacheDictionary>(trimLimit: 300, autoTrimCount: 100); - - this.innerDictionary.CacheRemoved += (s, e) => { + + this.innerDictionary.CacheRemoved += (s, e) => + { // まだ参照されている場合もあるのでDisposeはファイナライザ任せ this.CacheRemoveCount++; @@ -66,6 +68,7 @@ namespace OpenTween this.cancelTokenSource = new CancellationTokenSource(); } + finally { this.lockObject.ExitWriteLock(); } } /// @@ -95,12 +98,10 @@ namespace OpenTween return Task.Factory.StartNew(() => { Task cachedImageTask = null; - lock (this.lockObject) + this.lockObject.EnterUpgradeableReadLock(); + try { - if (force) - this.innerDictionary.Remove(address); - - if (this.innerDictionary.ContainsKey(address) && !this.innerDictionary[address].IsFaulted) + if (!force && this.innerDictionary.ContainsKey(address) && !this.innerDictionary[address].IsFaulted) cachedImageTask = this.innerDictionary[address]; if (cachedImageTask != null) @@ -108,34 +109,41 @@ namespace OpenTween cancelToken.ThrowIfCancellationRequested(); - using (var client = new OTWebClient() { Timeout = 10000 }) + this.lockObject.EnterWriteLock(); + try { - var imageTask = client.DownloadDataAsync(new Uri(address), cancelToken).ContinueWith(t => + using (var client = new OTWebClient() { Timeout = 10000 }) { - MemoryImage image = null; - if (t.Status == TaskStatus.RanToCompletion) + var imageTask = client.DownloadDataAsync(new Uri(address), cancelToken).ContinueWith(t => { - image = MemoryImage.CopyFromBytes(t.Result); - } + MemoryImage image = null; + if (t.Status == TaskStatus.RanToCompletion) + { + image = MemoryImage.CopyFromBytes(t.Result); + } - if (t.Exception != null) - t.Exception.Handle(e => e is WebException); + if (t.Exception != null) + t.Exception.Handle(e => e is WebException); - // FIXME: MemoryImage.Dispose() が正しいタイミングで呼ばれるように修正すべき - return image; - }, cancelToken); + // FIXME: MemoryImage.Dispose() が正しいタイミングで呼ばれるように修正すべき + return image; + }, cancelToken); - this.innerDictionary[address] = imageTask; + this.innerDictionary[address] = imageTask; - return imageTask; + return imageTask; + } } + finally { this.lockObject.ExitWriteLock(); } } + finally { this.lockObject.ExitUpgradeableReadLock(); } }, cancelToken).Unwrap(); } public MemoryImage TryGetFromCache(string address) { - lock (this.lockObject) + this.lockObject.EnterReadLock(); + try { if (!this.innerDictionary.ContainsKey(address)) return null; @@ -146,15 +154,18 @@ namespace OpenTween return imageTask.Result; } + finally { this.lockObject.ExitReadLock(); } } public void CancelAsync() { - lock (this.lockObject) + this.lockObject.EnterWriteLock(); + try { this.cancelTokenSource.Cancel(); this.cancelTokenSource = new CancellationTokenSource(); } + finally { this.lockObject.ExitWriteLock(); } } protected virtual void Dispose(bool disposing) @@ -165,7 +176,8 @@ namespace OpenTween { this.CancelAsync(); - lock (this.lockObject) + this.lockObject.EnterWriteLock(); + try { foreach (var item in this.innerDictionary) { @@ -177,6 +189,9 @@ namespace OpenTween this.innerDictionary.Clear(); this.cancelTokenSource.Dispose(); } + finally { this.lockObject.ExitWriteLock(); } + + this.lockObject.Dispose(); } } diff --git a/OpenTween/Resources/ChangeLog.txt b/OpenTween/Resources/ChangeLog.txt index 594d8b94..1010823d 100644 --- a/OpenTween/Resources/ChangeLog.txt +++ b/OpenTween/Resources/ChangeLog.txt @@ -2,6 +2,7 @@ ==== Ver 1.1.0-beta1(2013/xx/xx) * NEW: タブの表示位置を画面上部に変更可能に (thx @aokomoriuta!) + * CHG: アイコン読み込み処理の速度改善 * FIX: スペースが含まれているURLをブラウザで開こうとするとURLが分断されて複数のタブが開いてしまう問題を修正 (thx @5px!) * FIX: 画面更新時にInvalidOperationExceptionのエラーが発生する不具合を修正 -- 2.11.0