/// <summary> /// 指定された URL にある画像を非同期に取得するメソッド /// </summary> /// <param name="address">取得先の URL</param> /// <param name="force">キャッシュを使用せずに取得する場合は true</param> /// <returns>非同期に画像を取得するタスク</returns> public Task <MemoryImage> DownloadImageAsync(string address, bool force = false) { var cancelToken = this.cancelTokenSource.Token; return(Task.Factory.StartNew(() => { Task <MemoryImage> cachedImageTask = null; lock (this.lockObject) { if (force) { this.innerDictionary.Remove(address); } if (this.innerDictionary.ContainsKey(address) && !this.innerDictionary[address].IsFaulted) { cachedImageTask = this.innerDictionary[address]; } } if (cachedImageTask != null) { return cachedImageTask; } cancelToken.ThrowIfCancellationRequested(); using (var client = new OTWebClient() { Timeout = 10000 }) { var imageTask = client.DownloadDataAsync(new Uri(address), cancelToken).ContinueWith(t => { MemoryImage image = null; if (t.Status == TaskStatus.RanToCompletion) { image = MemoryImage.CopyFromBytes(t.Result); } if (t.Exception != null) { t.Exception.Handle(e => e is WebException); } // FIXME: MemoryImage.Dispose() が正しいタイミングで呼ばれるように修正すべき return image; }, cancelToken); lock (this.lockObject) { this.innerDictionary[address] = imageTask; } return imageTask; } }, cancelToken).Unwrap()); }
public new Task LoadAsync(string url) { this._ImageLocation = url; if (this.loadAsyncTask != null && !this.loadAsyncTask.IsCompleted) { this.CancelAsync(); } this.Image = base.InitialImage; Uri uri; try { uri = new Uri(url); } catch (UriFormatException) { uri = new Uri(Path.GetFullPath(url)); } var client = new OTWebClient(); client.DownloadProgressChanged += (s, e) => { this.OnLoadProgressChanged(new ProgressChangedEventArgs(e.ProgressPercentage, e.UserState)); }; this.loadAsyncCancelTokenSource = new CancellationTokenSource(); var cancelToken = this.loadAsyncCancelTokenSource.Token; var loadImageTask = client.DownloadDataAsync(uri, cancelToken); // UnobservedTaskException イベントを発生させないようにする loadImageTask.ContinueWith(t => { var ignore = t.Exception; }, TaskContinuationOptions.OnlyOnFaulted); var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); return(loadImageTask.ContinueWith(t => { client.Dispose(); if (t.IsFaulted) { throw t.Exception; } return MemoryImage.CopyFromBytes(t.Result); }, cancelToken) .ContinueWith(t => { if (!t.IsCanceled) { if (t.IsFaulted) { this.Image = base.ErrorImage; } else { this.Image = t.Result.Image; this.memoryImage = t.Result; } } var exp = t.Exception != null ? t.Exception.Flatten() : null; this.OnLoadCompleted(new AsyncCompletedEventArgs(exp, t.IsCanceled, null)); }, uiScheduler)); }