/// <summary> /// Gets a given tile at a specific zoom level. /// Checks the current caching provider for the file. If the file is present within /// the caching provider, a stream to it's contents is returned. This stream should be disposed as soon as the /// data from it is fully used. /// /// If the tile is not present within the tile cache, it is checked if the tile is currently being downloaded. /// If not so, a download job to download the tile is enqueued. /// /// In both cases - tile being downloaded or not - null is returned. /// </summary> /// <param name="zoom">The zoom level to get the tile from.</param> /// <param name="tile">The tile X/Y coordinates.</param> /// <returns>A stream to the tiles contents or null.</returns> public Stream GetTile(int zoom, MapVector tile) { TileDescriptor desc = new TileDescriptor(zoom, tile); if (_cachingProvider.HasTile(desc)) { return(_cachingProvider.GetTile(desc)); } else if (!_enqueuedTiles.Contains(desc)) { DownloadJob job = new DownloadJob(_mapProvider.GetTileUrl(GetNextServer(), desc.Zoom, desc.Tile), desc); job.OnFinished += Job_OnFinished; job.OnFailed += Job_OnFailed; try { _downloadMutex.WaitOne(); _enqueuedTiles.Add(desc); } finally { _downloadMutex.ReleaseMutex(); } _download.AddJob(job); } return(null); }