private MapShapeModelCollection ProcessItems(IRandomAccessStream shapeStream, ShapefileRecordInfoCollection recordInfos, CancellationTokenSource cancellationTokenSource) { if (cancellationTokenSource.IsCancellationRequested) { return(null); } int itemCount = recordInfos.Count; int maxDegreeOfParallelism = Environment.ProcessorCount; if (itemCount < maxDegreeOfParallelism) { maxDegreeOfParallelism = itemCount; } int remainder = itemCount % maxDegreeOfParallelism; int multiplier = (itemCount / maxDegreeOfParallelism) + (remainder > 0 ? 1 : 0); var token = cancellationTokenSource.Token; List <Task <MapShapeModelCollection> > tasks = new List <Task <MapShapeModelCollection> >(); for (int i = 0; i < maxDegreeOfParallelism; i++) { int start = i * multiplier; int end = Math.Min((i + 1) * multiplier, itemCount); ParseShapeTaskState taskState = new ParseShapeTaskState() { Start = start, End = end, Records = recordInfos, Stream = shapeStream, CancellationTokenSource = cancellationTokenSource, CoordinateConverter = this.CoordinateValueConverter }; var task = Task.Factory.StartNew <Task <MapShapeModelCollection> >(ParseShapes, taskState, token, TaskCreationOptions.AttachedToParent, TaskScheduler.Current).Unwrap(); tasks.Add(task); } Task.WaitAll(tasks.ToArray()); MapShapeModelCollection models = tasks[0].Result; for (int i = 1; i < maxDegreeOfParallelism; i++) { var modelsToMerge = tasks[i].Result; if (modelsToMerge == null) { continue; } foreach (var model in modelsToMerge) { models.Add(model); } } models.BoundingRect = recordInfos.BoundingRect; return(models); }
private static Task <MapShapeModelCollection> ParseShapes(object state) { ParseShapeTaskState taskState = (ParseShapeTaskState)state; var cancellationTokenSource = taskState.CancellationTokenSource; var token = cancellationTokenSource.Token; var task = Task.Factory.StartNew(async() => { using (var shapeStream = taskState.Stream.CloneStream()) { int start = taskState.Start; int end = taskState.End; var coordinateConverter = taskState.CoordinateConverter; var records = taskState.Records; MapShapeModelCollection shapeModels = new MapShapeModelCollection(); for (int i = start; i < end; i++) { if (cancellationTokenSource.IsCancellationRequested) { return(null); } int contentOffset = records[i].ContentOffset; shapeStream.Seek((ulong)contentOffset); int contentLength = records[i].ContentLength; byte[] content = new byte[contentLength]; await shapeStream.ReadAsync(content.AsBuffer(), (uint)contentLength, InputStreamOptions.Partial); EsriShapeType shapeType = (EsriShapeType)BitConverter.ToInt32(content, 0); if (shapeModels.Type == EsriShapeType.NullShape) { shapeModels.Type = shapeType; } // TODO: Consider specific support for "M" types (PointM, MultipointM, PolygonM) that support measure coordinate -- is this the Bubble visualization?. switch (shapeType) { case EsriShapeType.NullShape: shapeModels.Add(new NullShapeModel()); break; case EsriShapeType.Point: case EsriShapeType.PointM: case EsriShapeType.PointZ: CreatePoint(content, shapeModels, 4, coordinateConverter); break; case EsriShapeType.Polyline: case EsriShapeType.PolylineM: case EsriShapeType.PolylineZ: CreatePolyline(content, shapeModels, coordinateConverter); break; case EsriShapeType.Polygon: case EsriShapeType.PolygonM: case EsriShapeType.PolygonZ: CreatePolygon(content, shapeModels, coordinateConverter); break; default: throw new NotSupportedException("The supported ESRI shape types are Point(MZ), Polyline(MZ), and Polygon(MZ)."); } } return(shapeModels); } }, token).Unwrap(); return(task); }