public void GetImageAsync(FacebookImageDimensions requestedSize, GetImageSourceAsyncCallback callback) { Verify.IsNotNull(callback, "callback"); Assert.IsNotNull(SourceService); Assert.IsNotNull(SourceService.WebGetter); SmallUri ss = _GetSmallUriFromRequestedSize(requestedSize); if (ss == default(SmallUri)) { callback(this, new GetImageSourceCompletedEventArgs(new InvalidOperationException("The requested image doesn't exist"), false, this)); } BitmapSource img; if (_TryGetFromWeakCache(requestedSize, out img)) { callback(this, new GetImageSourceCompletedEventArgs(img, this)); } var userState = new _ImageCallbackState { Callback = callback, RequestedSize = requestedSize }; SourceService.WebGetter.GetImageSourceAsync(this, userState, ss, _AddWeakCacheCallback); }
public bool IsCached(FacebookImageDimensions requestedSize) { SmallUri sizedString = _GetSmallUriFromRequestedSize(requestedSize); //Assert.IsNotDefault(sizedString); string path; return(SourceService.WebGetter.TryGetImageFile(sizedString, out path)); }
private string _GetCacheLocation(SmallUri ssUri) { string path = _GenerateCachePath(ssUri); if (File.Exists(path)) { return(path); } return(null); }
private string _GenerateCachePath(SmallUri ssUri) { string key = ssUri.GetString(); if (key.Length > 100) { key = "hash(" + Utility.GetHashString(key) + ")_" + key.Substring(key.Length - 80); } return(Path.Combine(_cachePath, Utility.MakeValidFileName(key))); }
public void GetLocalImagePathAsync(object sender, object userState, SmallUri ssUri, SaveImageAsyncCallback callback) { //Verify.UriIsAbsolute(uri, "uri"); Verify.IsNotNull(sender, "sender"); // UserState may be null. // Verify.IsNotNull(userState, "userState"); Verify.IsNotNull(callback, "callback"); if (_disposed) { callback(this, new SaveImageCompletedEventArgs(new ObjectDisposedException("this"), false, userState)); return; } if (default(SmallUri) == ssUri) { callback(this, new SaveImageCompletedEventArgs(new ArgumentException("The requested image doesn't exist.", "ssUri"), false, userState)); return; } string cacheLocation = _GetCacheLocation(ssUri); if (cacheLocation != null) { callback(this, new SaveImageCompletedEventArgs(cacheLocation, userState)); return; } // Make asynchronous request to download the image and get the local path. var imageRequest = new _DataRequest { Sender = sender, UserState = userState, SmallUri = ssUri, Callback = callback, }; bool needToQueue = false; lock (_webLock) { needToQueue = !_asyncWebRequestPool.HasPendingRequests; _activeWebRequests.Push(imageRequest); } if (needToQueue) { _asyncWebRequestPool.QueueRequest(_ProcessNextWebRequest, null); _asyncWebRequestPool.QueueRequest(_ProcessNextWebRequest, null); } }
public void QueueImageRequest(SmallUri ssUri) { if (_disposed) { return; } if (ssUri == default(SmallUri)) { return; } //Verify.UriIsAbsolute(uri, "uri"); string path; if (TryGetImageFile(ssUri, out path)) { return; } bool needToQueue = false; lock (_localLock) { needToQueue = !_asyncWebRequestPool.HasPendingRequests; _passiveWebRequests.Push(ssUri); } if (needToQueue) { // When we queue web requests, do it twice to effectively use the pool. // Since _ProcessNextWebRequest operates in a tight loop flushing our list it's not aware // that the work can be shared. _asyncWebRequestPool.QueueRequest(DispatcherPriority.Background, _ProcessNextWebRequest, null); _asyncWebRequestPool.QueueRequest(DispatcherPriority.Background, _ProcessNextWebRequest, null); } }
private void _ProcessNextWebRequest(object unused) { if (_asyncWebRequestPool == null) { return; } var webClient = _asyncWebRequestPool.Tag as WebClient; Assert.IsNotNull(webClient); while (_asyncWebRequestPool != null) { // Retrieve the next data request for processing. _DataRequest activeRequest = null; SmallUri ssUri = default(SmallUri); bool isPassive = false; lock (_webLock) { while (_activeWebRequests.Count > 0) { activeRequest = _activeWebRequests.Pop(); Assert.IsNotNull(activeRequest); if (!activeRequest.Canceled) { ssUri = activeRequest.SmallUri; break; } } if (ssUri == default(SmallUri) && _passiveWebRequests.Count > 0) { ssUri = _passiveWebRequests.Pop(); isPassive = true; } if (ssUri == default(SmallUri)) { Assert.AreEqual(0, _activeWebRequests.Count); Assert.AreEqual(0, _passiveWebRequests.Count); return; } } try { string localCachePath = _GenerateCachePath(ssUri); if (!File.Exists(localCachePath)) { // There's a potential race here with other attempts to write the same file. // We don't really care because there's not much we can do about it when // it happens from multiple processes. string tempFile = Path.GetTempFileName(); Uri address = ssUri.GetUri(); try { webClient.DownloadFile(address, tempFile); } catch (WebException) { // Fail once, just try again. Servers are flakey. // Fails again let it throw. Caller is expected to catch. webClient.DownloadFile(address, tempFile); } // Should really block multiple web requests for the same file, which causes this... if (!Utility.TryFileMove(tempFile, localCachePath)) { return; } } if (!isPassive) { // If the _DataRequest has a SaveImageAsyncCallback then we're done. var saveImageCallback = activeRequest.Callback as SaveImageAsyncCallback; if (saveImageCallback != null) { saveImageCallback(this, new SaveImageCompletedEventArgs(localCachePath, activeRequest.UserState)); return; } bool needToQueue = false; lock (_localLock) { if (_asyncPhotoPool != null) { needToQueue = !_asyncPhotoPool.HasPendingRequests; _activePhotoRequests.Push(activeRequest); } } if (needToQueue) { _asyncPhotoPool.QueueRequest(_ProcessNextLocalRequest, null); } } } catch { } } }
private void _ProcessNextLocalRequest(object unused) { while (_asyncPhotoPool != null) { // Retrieve the next data request for processing. GetImageSourceAsyncCallback callback = null; object userState = null; object sender = null; SmallUri ssUri = default(SmallUri); lock (_localLock) { while (_activePhotoRequests.Count > 0) { _DataRequest nextDataRequest = _activePhotoRequests.Pop(); Assert.IsTrue(nextDataRequest.Callback is GetImageSourceAsyncCallback); if (!nextDataRequest.Canceled) { sender = nextDataRequest.Sender; callback = (GetImageSourceAsyncCallback)nextDataRequest.Callback; userState = nextDataRequest.UserState; ssUri = nextDataRequest.SmallUri; break; } } if (ssUri == default(SmallUri)) { Assert.AreEqual(0, _activePhotoRequests.Count); return; } } Assert.IsNotNull(callback); GetImageSourceCompletedEventArgs callbackArgs = null; string localCachePath = null; try { localCachePath = _GetCacheLocation(ssUri); if (localCachePath == null) { callbackArgs = new GetImageSourceCompletedEventArgs(new FileNotFoundException(), false, userState); } else { using (Stream imageStream = File.Open(localCachePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { callbackArgs = new GetImageSourceCompletedEventArgs(_GetBitmapSourceFromStream(imageStream), userState); } } } catch (Exception e) { if (!string.IsNullOrEmpty(localCachePath)) { // If the cache is bad try removing the file so we can fetch it correctly next time. try { File.Delete(localCachePath); } catch { } } callbackArgs = new GetImageSourceCompletedEventArgs(e, false, userState); } _callbackDispatcher.BeginInvoke(callback, sender, callbackArgs); } }
public bool TryGetImageFile(SmallUri ssUri, out string path) { _Verify(); path = _GetCacheLocation(ssUri); return(path != null); }
public void GetImageSourceAsync(object sender, object userState, SmallUri ssUri, GetImageSourceAsyncCallback callback) { //Verify.UriIsAbsolute(uri, "uri"); Verify.IsNotNull(sender, "sender"); // UserState may be null. // Verify.IsNotNull(userState, "userState"); Verify.IsNotNull(callback, "callback"); if (_disposed) { callback(this, new GetImageSourceCompletedEventArgs(new ObjectDisposedException("this"), false, userState)); return; } if (default(SmallUri) == ssUri) { callback(this, new GetImageSourceCompletedEventArgs(new ArgumentException("The requested image doesn't exist.", "ssUri"), false, userState)); return; } // Make asynchronous request to get ImageSource object from the data feed. var imageRequest = new _DataRequest { Sender = sender, UserState = userState, SmallUri = ssUri, Callback = callback, }; bool needToCache = _GetCacheLocation(ssUri) == null; if (needToCache) { bool needToQueue = false; lock (_webLock) { needToQueue = !_asyncWebRequestPool.HasPendingRequests; _activeWebRequests.Push(imageRequest); } if (needToQueue) { _asyncWebRequestPool.QueueRequest(_ProcessNextWebRequest, null); _asyncWebRequestPool.QueueRequest(_ProcessNextWebRequest, null); } } else { bool needToQueue = false; lock (_localLock) { needToQueue = !_asyncPhotoPool.HasPendingRequests; _activePhotoRequests.Push(imageRequest); } if (needToQueue) { _asyncPhotoPool.QueueRequest(_ProcessNextLocalRequest, null); } } }
internal SaveFileCompletedEventArgs(string path, object userState, SmallUri uri) : base(null, false, userState) { Verify.IsNeitherNullNorEmpty(path, "path"); Assert.IsTrue(File.Exists(path)); FilePath = path; SmallUri = uri; }
public PageCompletedEventArgs(string pageContent, object userState, SmallUri uri) : base(null, false, userState) { PageContent = pageContent; SmallUri = uri; }
/// <summary> /// Download the web page specified in the ssUri /// </summary> /// <param name="sender">sender of the request</param> /// <param name="userState">user state - can be null</param> /// <param name="ssUri">uri to the page to download</param> /// <param name="callback">callback to call when download is complete</param> public void DownloadPageAsync(object sender, object userState, SmallUri ssUri, PageAsyncCallback callback) { if (_disposed) { callback(this, new PageCompletedEventArgs(new ObjectDisposedException("this"), false, userState)); return; } if (default(SmallUri) == ssUri) { if (callback != null) callback(this, new PageCompletedEventArgs(new ArgumentException("The requested page doesn't exist.", "ssUri"), false, userState)); return; } // Make asynchronous request to download the image and get the local path. var pageRequest = new PageRequest { Sender = sender, UserState = userState, SmallUri = ssUri, Callback = callback }; bool needToQueue = false; lock (_webLock) { needToQueue = !_asyncWebRequestPool.HasPendingRequests; _activeWebRequests.Enqueue(pageRequest); } if (needToQueue) _asyncWebRequestPool.QueueRequest(_ProcessNextWebRequest, null); }
/// <summary> /// Download the specified file asynchroniously /// </summary> /// <param name="sender">sender of the request</param> /// <param name="userState">user state - can be null</param> /// <param name="ssUri">uri to the file to download</param> /// <param name="callback">callback to call when download is complete - can be null if you just want to download it in the background</param> /// <param name="pathToStore">directory where the file should be stored</param> /// <param name="fileName">filename of the file. If null then MD5 hash is computed from the uri and used as a filename - good to cache images</param> public void DownloadFileAsync(object sender, object userState, SmallUri ssUri, SaveFileAsyncCallback callback, string pathToStore, string fileName = null) { if (_disposed) { callback(this, new SaveFileCompletedEventArgs(new ObjectDisposedException("this"), false, userState)); return; } if (default(SmallUri) == ssUri) { if (callback != null) callback(this, new SaveFileCompletedEventArgs(new ArgumentException("The requested image doesn't exist.", "ssUri"), false, userState)); return; } if (String.IsNullOrEmpty(fileName)) fileName = ComputeUrlHash(ssUri.GetString()); string destinationFullPath = Path.Combine(pathToStore, fileName); if (File.Exists(destinationFullPath)) { callback(this, new SaveFileCompletedEventArgs(destinationFullPath, userState, ssUri)); return; } // Make asynchronous request to download the image and get the local path. var fileRequest = new FileRequest { Sender = sender, UserState = userState, SmallUri = ssUri, Callback = callback, DestinationFileName = Path.Combine(pathToStore, fileName) }; bool needToQueue = false; lock (_webLock) { needToQueue = !_asyncWebRequestPool.HasPendingRequests; if (callback != null) _activeWebRequests.Enqueue(fileRequest); else _passiveWebRequests.Enqueue(fileRequest); } if (needToQueue) _asyncWebRequestPool.QueueRequest(_ProcessNextWebRequest, null); }