OSDN Git Service

OTPictureBoxに非同期に画像をロードするためのメソッドを追加
authorKimura Youichi <kim.upsilon@bucyou.net>
Sat, 31 May 2014 16:21:10 +0000 (01:21 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Sat, 7 Jun 2014 13:22:40 +0000 (22:22 +0900)
OpenTween.Tests/OTPictureBoxTest.cs
OpenTween/OTPictureBox.cs
OpenTween/Tween.cs
OpenTween/Tween.resx
OpenTween/TweetThumbnail.cs
OpenTween/UserInfoDialog.cs
OpenTween/UserInfoDialog.resx

index f62b19a..453ad1a 100644 (file)
@@ -23,6 +23,8 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
 using System.Windows.Forms;
 using Xunit;
 using Xunit.Extensions;
@@ -90,6 +92,49 @@ namespace OpenTween
             }
         }
 
+        [Fact]
+        public async Task SetImageFromAsync_Test()
+        {
+            using (var picbox = new OTPictureBox())
+            {
+                // Mono でのテスト実行時にデッドロックする問題の対策
+                SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
+
+                var tcs = new TaskCompletionSource<MemoryImage>();
+
+                var setImageTask = picbox.SetImageFromTask(() => tcs.Task);
+
+                Assert.Equal(picbox.InitialImage, ((PictureBox)picbox).Image);
+
+                var image = this.CreateDummyImage();
+                tcs.SetResult(image);
+                await setImageTask;
+
+                Assert.Equal(image, picbox.Image);
+            }
+        }
+
+        [Fact]
+        public async Task SetImageFromAsync_ErrorTest()
+        {
+            using (var picbox = new OTPictureBox())
+            {
+                // Mono でのテスト実行時にデッドロックする問題の対策
+                SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
+
+                var tcs = new TaskCompletionSource<MemoryImage>();
+
+                var setImageTask = picbox.SetImageFromTask(() => tcs.Task);
+
+                Assert.Equal(picbox.InitialImage, ((PictureBox)picbox).Image);
+
+                tcs.SetException(new InvalidImageException());
+                await setImageTask;
+
+                Assert.Equal(picbox.ErrorImage, ((PictureBox)picbox).Image);
+            }
+        }
+
         MemoryImage CreateDummyImage()
         {
             using (var bitmap = new Bitmap(100, 100))
index 17162b4..028a738 100644 (file)
@@ -30,6 +30,7 @@ using System.Drawing;
 using System.Threading.Tasks;
 using System.Threading;
 using System.Net;
+using System.Net.Http;
 using System.IO;
 
 namespace OpenTween
@@ -94,6 +95,27 @@ namespace OpenTween
             base.SizeMode = this.currentSizeMode;
         }
 
+        public async Task SetImageFromTask(Func<Task<MemoryImage>> imageTask)
+        {
+            try
+            {
+                this.ShowInitialImage();
+                this.Image = await imageTask();
+            }
+            catch (Exception)
+            {
+                this.ShowErrorImage();
+                try
+                {
+                    throw;
+                }
+                catch (HttpRequestException) { }
+                catch (InvalidImageException) { }
+                catch (TaskCanceledException) { }
+                catch (WebException) { }
+            }
+        }
+
         protected override void OnPaint(PaintEventArgs pe)
         {
             try
index 2467f9f..401fbc4 100644 (file)
@@ -9797,25 +9797,16 @@ namespace OpenTween
         {
             if (this._curPost == null) return;
 
-            var imageUrl = this._curPost.ImageUrl;
-            try
+            await this.UserPicture.SetImageFromTask(async () =>
             {
-                var image = await this.IconCache.DownloadImageAsync(imageUrl, force: true);
+                var imageUrl = this._curPost.ImageUrl;
 
-                this.ClearUserPicture();
-                this.UserPicture.Image = image.Clone();
-            }
-            catch (Exception)
-            {
-                this.UserPicture.ShowErrorImage();
-                try
-                {
-                    throw;
-                }
-                catch (HttpRequestException) { }
-                catch (InvalidImageException) { }
-                catch (TaskCanceledException) { }
-            }
+                var image = await this.IconCache.DownloadImageAsync(imageUrl, force: true)
+                    .ConfigureAwait(false);
+
+                return await image.CloneAsync()
+                    .ConfigureAwait(false);
+            });
         }
 
         private void SaveOriginalSizeIconPictureToolStripMenuItem_Click(object sender, EventArgs e)
index 0d6a895..cd40ec2 100644 (file)
   <data name="ApiUsageInfoMenuItem.Size" type="System.Drawing.Size, System.Drawing">
     <value>301, 24</value>
   </data>
+  <data name="UserPicture.InitialImage" type="System.Resources.ResXNullRef, System.Windows.Forms">
+    <value />
+  </data>
   <data name="UserPicture.Location" type="System.Drawing.Point, System.Drawing">
     <value>4, 4</value>
   </data>
index 261247e..9439d76 100644 (file)
@@ -85,7 +85,7 @@ namespace OpenTween
                     picbox.Tag = thumb;
                     picbox.ContextMenu = CreateContextMenu(thumb);
 
-                    var loadTask = this.SetThumbnailImageAsync(picbox, thumb, cancelToken);
+                    var loadTask = picbox.SetImageFromTask(() => thumb.LoadThumbnailImageAsync(cancelToken));
                     loadTasks.Add(loadTask);
 
                     var tooltipText = thumb.TooltipText;
@@ -107,27 +107,6 @@ namespace OpenTween
             await Task.WhenAll(loadTasks).ConfigureAwait(false);
         }
 
-        private async Task SetThumbnailImageAsync(OTPictureBox picbox, ThumbnailInfo thumbInfo,
-            CancellationToken cancelToken)
-        {
-            try
-            {
-                picbox.ShowInitialImage();
-                picbox.Image = await thumbInfo.LoadThumbnailImageAsync(cancelToken);
-            }
-            catch (Exception)
-            {
-                picbox.ShowErrorImage();
-                try
-                {
-                    throw;
-                }
-                catch (HttpRequestException) { }
-                catch (InvalidImageException) { }
-                catch (TaskCanceledException) { }
-            }
-        }
-
         private ContextMenu CreateContextMenu(ThumbnailInfo thumb)
         {
             var contextMenu = new ContextMenu();
index 96f9028..1286011 100644 (file)
@@ -173,11 +173,17 @@ namespace OpenTween
             if (imageUri == null)
                 return;
 
-            using (var http = MyCommon.CreateHttpClient())
+            await this.UserPicture.SetImageFromTask(async () =>
             {
-                var imageStream = await http.GetStreamAsync(imageUri.Replace("_normal", "_bigger"));
-                this.UserPicture.Image = await MemoryImage.CopyFromStreamAsync(imageStream);
-            }
+                using (var http = MyCommon.CreateHttpClient())
+                {
+                    var imageStream = await http.GetStreamAsync(imageUri.Replace("_normal", "_bigger"))
+                        .ConfigureAwait(false);
+
+                    return await MemoryImage.CopyFromStreamAsync(imageStream)
+                        .ConfigureAwait(false);
+                }
+            });
         }
 
         private async Task SetLinkLabelWebAsync(string uri)
index c0a8be8..69e7e36 100644 (file)
   <data name="UserPicture.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
     <value>NoControl</value>
   </data>
+  <data name="UserPicture.InitialImage" type="System.Resources.ResXNullRef, System.Windows.Forms">
+    <value />
+  </data>
   <data name="UserPicture.Location" type="System.Drawing.Point, System.Drawing">
     <value>12, 59</value>
   </data>