OSDN Git Service

TweetThumbnailの排他制御にlockステートメントを使用
authorKimura Youichi <kim.upsilon@bucyou.net>
Mon, 17 Feb 2014 10:33:28 +0000 (19:33 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Mon, 17 Feb 2014 15:03:10 +0000 (00:03 +0900)
OpenTween/TweetThumbnail.cs

index 9bb4588..3747217 100644 (file)
@@ -46,6 +46,8 @@ namespace OpenTween
         public event EventHandler<ThumbnailDoubleClickEventArgs> ThumbnailDoubleClick;
         public event EventHandler<ThumbnailImageSearchEventArgs> ThumbnailImageSearchClick;
 
+        private object uiLockObj = new object();
+
         public ThumbnailInfo Thumbnail
         {
             get { return this.pictureBox[this.scrollBar.Value].Tag as ThumbnailInfo; }
@@ -73,47 +75,50 @@ namespace OpenTween
                     {
                         var thumbnails = t.Result;
 
-                        this.SetThumbnailCount(thumbnails.Count);
-                        if (thumbnails.Count == 0) return;
-
-                        for (int i = 0; i < thumbnails.Count; i++)
+                        lock (this.uiLockObj)
                         {
-                            var thumb = thumbnails[i];
-                            var picbox = this.pictureBox[i];
+                            this.SetThumbnailCount(thumbnails.Count);
+                            if (thumbnails.Count == 0) return;
 
-                            picbox.Tag = thumb;
-                            picbox.ContextMenu = CreateContextMenu(thumb);
+                            for (int i = 0; i < thumbnails.Count; i++)
+                            {
+                                var thumb = thumbnails[i];
+                                var picbox = this.pictureBox[i];
 
-                            picbox.ShowInitialImage();
+                                picbox.Tag = thumb;
+                                picbox.ContextMenu = CreateContextMenu(thumb);
 
-                            thumb.LoadThumbnailImageAsync(cancelToken)
-                                .ContinueWith(t2 =>
-                                {
-                                    if (t2.IsFaulted)
-                                        t2.Exception.Flatten().Handle(x => x is WebException || x is InvalidImageException || x is TaskCanceledException);
+                                picbox.ShowInitialImage();
 
-                                    if (t2.IsFaulted || t2.IsCanceled)
+                                thumb.LoadThumbnailImageAsync(cancelToken)
+                                    .ContinueWith(t2 =>
                                     {
-                                        picbox.ShowErrorImage();
-                                        return;
-                                    }
+                                        if (t2.IsFaulted)
+                                            t2.Exception.Flatten().Handle(x => x is WebException || x is InvalidImageException || x is TaskCanceledException);
 
-                                    picbox.Image = t2.Result;
-                                },
-                                CancellationToken.None, TaskContinuationOptions.AttachedToParent, uiScheduler);
+                                        if (t2.IsFaulted || t2.IsCanceled)
+                                        {
+                                            picbox.ShowErrorImage();
+                                            return;
+                                        }
 
-                            var tooltipText = thumb.TooltipText;
-                            if (!string.IsNullOrEmpty(tooltipText))
-                            {
-                                this.toolTip.SetToolTip(picbox, tooltipText);
+                                        picbox.Image = t2.Result;
+                                    },
+                                    CancellationToken.None, TaskContinuationOptions.AttachedToParent, uiScheduler);
+
+                                var tooltipText = thumb.TooltipText;
+                                if (!string.IsNullOrEmpty(tooltipText))
+                                {
+                                    this.toolTip.SetToolTip(picbox, tooltipText);
+                                }
+
+                                cancelToken.ThrowIfCancellationRequested();
                             }
 
-                            cancelToken.ThrowIfCancellationRequested();
+                            if (thumbnails.Count > 1)
+                                this.scrollBar.Enabled = true;
                         }
 
-                        if (thumbnails.Count > 1)
-                            this.scrollBar.Enabled = true;
-
                         if (this.ThumbnailLoading != null)
                             this.ThumbnailLoading(this, new EventArgs());
                     },
@@ -177,23 +182,6 @@ namespace OpenTween
             if (this.task == null || this.task.IsCompleted) return;
 
             this.cancelTokenSource.Cancel();
-
-            // this.task.Status は、GetThumbailInfo() の実行中であれば TaskStatus.WaitingForActivation となる。
-            // ContinueWith の処理も含めて終了していれば RanToCompletion などになる。
-            // もしこれが Running である場合は、PictureBox に対する操作の途中である可能性が高いため
-            // 必ず Wait() を実行してタスクの終了を待つ。
-            // (ContinueWith のタスクは ThumbnailLoading イベントが足を引っ張らない限り20ms程で完了する)
-
-            if (this.task.Status != TaskStatus.Running) return;
-
-            try
-            {
-                this.task.Wait();
-            }
-            catch (AggregateException ae)
-            {
-                ae.Handle(e => e is TaskCanceledException);
-            }
         }
 
         /// <summary>