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); } }
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 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); } } }