private static Task ParseAttributes(object state)
        {
            var taskState = (ParseDataTaskState)state;
            var cancellationTokenSource = taskState.CancellationTokenSource;
            var token = cancellationTokenSource.Token;

            var task = Task.Factory.StartNew(
                async() =>
            {
                using (var dataStream = taskState.Stream.CloneStream())
                {
                    int start            = taskState.Start;
                    int end              = taskState.End;
                    DbfHeader dbfHeader  = taskState.DbfHeader;
                    var shapeModels      = taskState.ShapeModels;
                    var valueConverter   = taskState.ValueConverter;
                    var attributesToLoad = taskState.AttributesToLoad;

                    dataStream.Seek((ulong)(dbfHeader.RecordsOffset + start * dbfHeader.RecordLength));

                    for (int i = start; i < end; i++)
                    {
                        if (cancellationTokenSource.IsCancellationRequested)
                        {
                            return;
                        }

                        var shapeModel = shapeModels[i] as MapShapeModel;
                        byte[] record  = new byte[dbfHeader.RecordLength];
                        await dataStream.ReadAsync(record.AsBuffer(), (uint)dbfHeader.RecordLength, InputStreamOptions.Partial);

                        // Data records are preceded by one byte; that is, a space (20H) if the record is not deleted, an asterisk (2AH) if the record is deleted.
                        int offset = 1;
                        foreach (var field in dbfHeader.Fields)
                        {
                            if (attributesToLoad == null || attributesToLoad.Contains(field.Name))
                            {
                                string value         = dbfHeader.Encoding.GetString(record, offset, field.Length);
                                object propertyValue = TransformDbfValue(field, value, valueConverter);

                                shapeModel.Attributes[field.Name] = propertyValue;
                            }

                            offset += field.Length;
                        }
                    }
                }
            },
                token).Unwrap();

            return(task);
        }
        private static Task <DbfHeader> BuildDbfHeaderData(IRandomAccessStream stream, Encoding encoding, CancellationTokenSource cancellationTokenSource)
        {
            var token = cancellationTokenSource.Token;

            var task = Task.Factory.StartNew(async() =>
            {
                if (cancellationTokenSource.IsCancellationRequested)
                {
                    return(null);
                }

                if (stream.Size < 32)
                {
                    throw new NotSupportedException(InvalidFormat);
                }

                using (var dataStream = stream.CloneStream())
                {
                    byte[] header = new byte[32];
                    await dataStream.ReadAsync(header.AsBuffer(), 32u, InputStreamOptions.Partial);

                    byte fileType = header[0];
                    if (!AllowedTypes.Contains(fileType))
                    {
                        throw new NotSupportedException(InvalidFormat);
                    }

                    DbfHeader dbfHeader     = new DbfHeader();
                    dbfHeader.RecordsCount  = BitConverter.ToInt32(header, 4);
                    dbfHeader.RecordsOffset = BitConverter.ToInt16(header, 8);
                    dbfHeader.RecordLength  = BitConverter.ToInt16(header, 10);

                    if (encoding == null)
                    {
                        byte languageDriver = header[29];
                        encoding            = DbfEncoding.GetEncoding(languageDriver);
                    }

                    dbfHeader.Encoding = encoding;

                    // header is 32 bytes + n field descriptors * 32 bytes + carriage return byte (0x0D)
                    int fieldDescriptorCount = (dbfHeader.RecordsOffset - 32 - 1) / 32;
                    byte[] fieldDescriptor;
                    DbfFieldInfo dbfField;
                    for (int i = 0; i < fieldDescriptorCount; i++)
                    {
                        if (cancellationTokenSource.IsCancellationRequested)
                        {
                            return(null);
                        }

                        fieldDescriptor = new byte[32];
                        await dataStream.ReadAsync(fieldDescriptor.AsBuffer(), 32u, InputStreamOptions.Partial);

                        dbfField               = new DbfFieldInfo();
                        dbfField.Name          = encoding.GetString(fieldDescriptor, 0, 11).Replace("\0", string.Empty);
                        dbfField.NativeDbfType = (char)fieldDescriptor[11];

                        dbfField.Length       = fieldDescriptor[16];
                        dbfField.DecimalCount = fieldDescriptor[17];

                        dbfHeader.Fields.Add(dbfField);
                    }

                    return(dbfHeader);
                }
            },
                                             token).Unwrap();

            return(task);
        }
        private MapShapeModelCollection ProcessDataItems(MapShapeModelCollection shapeModels, DbfHeader dbfHeader, IRandomAccessStream dataStream, CancellationTokenSource cancellationTokenSource)
        {
            if (cancellationTokenSource.IsCancellationRequested)
            {
                return(null);
            }

            var token = cancellationTokenSource.Token;

            int itemCount = dbfHeader.RecordsCount;
            int maxDegreeOfParallelism = Environment.ProcessorCount;

            if (itemCount < maxDegreeOfParallelism)
            {
                maxDegreeOfParallelism = itemCount;
            }

            int remainder  = itemCount % maxDegreeOfParallelism;
            int multiplier = (itemCount / maxDegreeOfParallelism) + (remainder > 0 ? 1 : 0);

            List <Task> tasks = new List <Task>();

            for (int i = 0; i < maxDegreeOfParallelism; i++)
            {
                int start = i * multiplier;
                int end   = Math.Min((i + 1) * multiplier, itemCount);

                var taskState = new ParseDataTaskState()
                {
                    Start                   = start,
                    End                     = end,
                    DbfHeader               = dbfHeader,
                    Stream                  = dataStream,
                    ShapeModels             = shapeModels,
                    CancellationTokenSource = cancellationTokenSource,
                    ValueConverter          = this.AttributeValueConverter,
                    AttributesToLoad        = this.AttributesToLoad
                };
                var task = Task.Factory.StartNew <Task>(ParseAttributes, taskState, token, TaskCreationOptions.AttachedToParent, TaskScheduler.Current).Unwrap();

                tasks.Add(task);
            }

            Task.WaitAll(tasks.ToArray());

            return(shapeModels);
        }