From: Kimura Youichi Date: Sat, 31 May 2014 16:21:10 +0000 (+0900) Subject: OTPictureBoxに非同期に画像をロードするためのメソッドを追加 X-Git-Tag: OpenTween_v1.2.2~32 X-Git-Url: http://git.osdn.net/view?p=opentween%2Fopen-tween.git;a=commitdiff_plain;h=fdad4573422dec9910c786d3f29d1a0f27091924 OTPictureBoxに非同期に画像をロードするためのメソッドを追加 --- diff --git a/OpenTween.Tests/OTPictureBoxTest.cs b/OpenTween.Tests/OTPictureBoxTest.cs index f62b19a8..453ad1ae 100644 --- a/OpenTween.Tests/OTPictureBoxTest.cs +++ b/OpenTween.Tests/OTPictureBoxTest.cs @@ -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(); + + 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(); + + 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)) diff --git a/OpenTween/OTPictureBox.cs b/OpenTween/OTPictureBox.cs index 17162b45..028a738c 100644 --- a/OpenTween/OTPictureBox.cs +++ b/OpenTween/OTPictureBox.cs @@ -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> 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 diff --git a/OpenTween/Tween.cs b/OpenTween/Tween.cs index 2467f9fc..401fbc48 100644 --- a/OpenTween/Tween.cs +++ b/OpenTween/Tween.cs @@ -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) diff --git a/OpenTween/Tween.resx b/OpenTween/Tween.resx index 0d6a8952..cd40ec2f 100644 --- a/OpenTween/Tween.resx +++ b/OpenTween/Tween.resx @@ -3006,6 +3006,9 @@ 301, 24 + + + 4, 4 diff --git a/OpenTween/TweetThumbnail.cs b/OpenTween/TweetThumbnail.cs index 261247e7..9439d76d 100644 --- a/OpenTween/TweetThumbnail.cs +++ b/OpenTween/TweetThumbnail.cs @@ -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(); diff --git a/OpenTween/UserInfoDialog.cs b/OpenTween/UserInfoDialog.cs index 96f90280..1286011f 100644 --- a/OpenTween/UserInfoDialog.cs +++ b/OpenTween/UserInfoDialog.cs @@ -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) diff --git a/OpenTween/UserInfoDialog.resx b/OpenTween/UserInfoDialog.resx index c0a8be88..69e7e36b 100644 --- a/OpenTween/UserInfoDialog.resx +++ b/OpenTween/UserInfoDialog.resx @@ -708,6 +708,9 @@ NoControl + + + 12, 59