public async Task <Dictionary <string, Record> > writeGeoTag(Dictionary <string, Record> recordDict, BlockingCollection <string> fileQueue, string inPath, string outPath)
        {
            int mQueueSize = fileQueue.Count;

            progressForm = new ProgressForm("Writing geotags to photos...");
            string[] _files = Directory.GetFiles(inPath);
            progressForm.Show();
            progressForm.BringToFront();
            progressForm.cancel += cancelImport;
            cts = new CancellationTokenSource();
            var token            = cts.Token;
            var progressHandler1 = new Progress <int>(value =>
            {
                progressForm.ProgressValue = value;
                progressForm.Message       = "Geotagging, please wait... " + value.ToString() + "% completed\n" +
                                             geoTagCount + " of " + mQueueSize + " photos geotagged\n" +
                                             "Photos with no geomark: " + stationaryCount + "\n" + "Photos with no gps point: " + errorCount + "\n";
            });
            var progressValue = progressHandler1 as IProgress <int>;

            geoTagCount     = 0;
            errorCount      = 0;
            stationaryCount = 0;
            Dictionary <string, Record> newRecordDict = new Dictionary <string, Record>();

            int processors       = Environment.ProcessorCount;
            int minWorkerThreads = processors;
            int minIOThreads     = processors;
            int maxWorkerThreads = processors;
            int maxIOThreads     = processors;

            //ThreadPool.SetMinThreads(minWorkerThreads, minIOThreads);
            ThreadPool.SetMaxThreads(maxWorkerThreads, maxIOThreads);
            await Task.Factory.StartNew(() =>
            {
                try
                {
                    while (fileQueue.Count != 0)
                    {
                        if (token.IsCancellationRequested)
                        {
                            token.ThrowIfCancellationRequested();
                        }
                        Parallel.Invoke(
                            () =>
                        {
                            ThreadInfo threadInfo      = new ThreadInfo();
                            threadInfo.OutPath         = outPath;
                            threadInfo.Length          = mQueueSize;
                            threadInfo.ProgressHandler = progressHandler1;
                            threadInfo.File            = fileQueue.Take();
                            try
                            {
                                Record r          = recordDict[Path.GetFileNameWithoutExtension(threadInfo.File)];
                                threadInfo.Record = r;

                                if (r.GeoMark)
                                {
                                    Record newRecord = null;
                                    newRecord        = ProcessFile(threadInfo).Result;
                                    newRecordDict.Add(r.PhotoName, r);
                                }
                                else
                                {
                                    object a = "nogps";
                                    incrementGeoTagError(a);
                                }
                            }
                            catch (KeyNotFoundException ex)
                            {
                                object a = "nokey";
                                incrementGeoTagError(a);
                            }
                        });
                    }
                }
                catch (OperationCanceledException)
                {
                    cts.Dispose();
                }
            }, cts.Token);

            progressForm.Invoke(
                new MethodInvoker(() => progressValue.Report(100)
                                  ));
            progressForm.enableOK();
            progressForm.disableCancel();
            return(newRecordDict);
        }
        private Record readData(ThreadInfo threadInfo)
        {
            string outPath       = threadInfo.OutPath;
            int    length        = threadInfo.Length;
            string file          = Path.GetFullPath(threadInfo.File);
            string photo         = file;
            Image  image         = new Bitmap(file);
            Record r             = new Record(photo);
            var    progressValue = threadInfo.ProgressHandler as IProgress <int>;

            lock (obj)
            {
                id++;
            }
            PropertyItem[] propItems        = image.PropertyItems;
            PropertyItem   propItemLatRef   = image.GetPropertyItem(0x0001);
            PropertyItem   propItemLat      = image.GetPropertyItem(0x0002);
            PropertyItem   propItemLonRef   = image.GetPropertyItem(0x0003);
            PropertyItem   propItemLon      = image.GetPropertyItem(0x0004);
            PropertyItem   propItemAltRef   = image.GetPropertyItem(0x0005);
            PropertyItem   propItemAlt      = image.GetPropertyItem(0x0006);
            PropertyItem   propItemDateTime = image.GetPropertyItem(0x0132);

            image.Dispose();
            byte[]   latBytes      = propItemLat.Value;
            byte[]   latRefBytes   = propItemLatRef.Value;
            byte[]   lonBytes      = propItemLon.Value;
            byte[]   lonRefBytes   = propItemLonRef.Value;
            byte[]   altRefBytes   = propItemAltRef.Value;
            byte[]   altBytes      = propItemAlt.Value;
            byte[]   dateTimeBytes = propItemDateTime.Value;
            string   latitudeRef   = ASCIIEncoding.UTF8.GetString(latRefBytes);
            string   longitudeRef  = ASCIIEncoding.UTF8.GetString(lonRefBytes);
            string   altRef        = ASCIIEncoding.UTF8.GetString(altRefBytes);
            double   latitude      = byteToDegrees(latBytes);
            double   longitude     = byteToDegrees(lonBytes);
            double   altitude      = byteToDecimal(altBytes);
            DateTime dateTime      = byteToDate(dateTimeBytes);

            if (latitudeRef.Equals("S\0"))
            {
                latitude = -latitude;
            }
            if (longitudeRef.Equals("W\0"))
            {
                longitude = -longitude;
            }
            if (!altRef.Equals("\0"))
            {
                altitude = -altitude;
            }
            r.Latitude  = latitude;
            r.Longitude = longitude;
            r.Altitude  = altitude;
            r.TimeStamp = dateTime;
            r.Path      = Path.GetFullPath(file);
            r.Id        = id.ToString();

            lock (obj)
            {
                addRecord(photo, r);
                geoTagCount++;
                setMinMax(latitude, longitude);
                double percent    = ((double)geoTagCount / length) * 100;
                int    percentInt = (int)(Math.Round(percent));
                if (progressValue != null)
                {
                    progressValue = threadInfo.ProgressHandler;
                    progressForm.Invoke(
                        new MethodInvoker(() => progressValue.Report(percentInt)
                                          ));
                }
            }
            return(r);
        }