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);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="path"></param>
        /// <param name="allRecords"></param>
        /// <returns></returns>
        public async Task <Dictionary <string, Record> > readFromDatabase(string path, Boolean allRecords)
        {
            Dictionary <string, Record> recordDict = new Dictionary <string, Record>();
            ProgressForm progressForm = new ProgressForm("Reading from database...");
            DataTable    table        = new DataTable();

            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       = "Database read, please wait... " + value.ToString() + "% completed";
            });
            var progressValue = progressHandler1 as IProgress <int>;

            try
            {
                await Task.Run(() =>
                {
                    if (token.IsCancellationRequested)
                    {
                        token.ThrowIfCancellationRequested();
                    }
                    string connectionString = string.Format("Provider={0}; Data Source={1}; Jet OLEDB:Engine Type={2}",
                                                            "Microsoft.Jet.OLEDB.4.0", path, 5);
                    connection = new OleDbConnection(connectionString);
                    //string connectionStr = connection.ConnectionString;
                    string strSQL;
                    string lengthSQL; //sql count string
                    int length;       //number of records to process

                    if (allRecords)
                    {
                        strSQL    = "SELECT * FROM PhotoList";
                        lengthSQL = "SELECT Count(Photo) FROM PhotoList;";
                    }
                    else
                    {
                        strSQL    = "SELECT * FROM PhotoList WHERE PhotoList.GeoMark = true;";
                        lengthSQL = "SELECT Count(PhotoID) FROM PhotoList WHERE PhotoList.GeoMark = true;";
                    }
                    OleDbCommand commandLength = new OleDbCommand(lengthSQL, connection);
                    OleDbCommand command       = new OleDbCommand(strSQL, connection);
                    connection.Open();

                    OleDbDataReader readerColumn = command.ExecuteReader(CommandBehavior.KeyInfo);
                    DataTable schemaTable        = readerColumn.GetSchemaTable();

                    foreach (DataRow col in schemaTable.Rows)
                    {
                        string c = col.Field <String>("ColumnName");
                        table.Columns.Add(c);
                    }

                    readerColumn.Close();
                    length = (Int32)commandLength.ExecuteScalar();
                    using (OleDbDataReader reader = command.ExecuteReader())
                    {
                        int i = 0;
                        while (reader.Read())
                        {
                            Object[] row = new Object[reader.FieldCount];
                            reader.GetValues(row);
                            String photo = (string)row[1];
                            Record r     = buildDictionary(i, row).Result;
                            //Record r = buildDictionary(ref table, row);
                            recordDict.Add(r.PhotoName, r);
                            i++;
                            double percent = ((double)i / length) * 100;
                            int percentInt = (int)Math.Ceiling(percent);
                            if (progressValue != null)
                            {
                                progressValue.Report(percentInt);
                            }
                            //token.ThrowIfCancellationRequested();
                        }
                    }
                }, cts.Token);
            }
            catch (ArgumentException ex)
            {
            }
            catch (NullReferenceException ex)
            {
                //txtConsole.AppendText(ex.StackTrace);
            }
            catch (OperationCanceledException)
            {
                cts.Dispose();
            }
            connection.Close();
            progressForm.Close();
            return(recordDict);
        }
        public async Task <GMapOverlay> readGeoTag(BlockingCollection <string> fileQueue, string folderPath, string layer, string color)
        {
            int mQueueSize = fileQueue.Count;

            string[]    files   = Directory.GetFiles(folderPath);
            GMapOverlay overlay = new GMapOverlay(layer);

            progressForm = new ProgressForm("Importing Photos...");
            progressForm.Show();
            progressForm.BringToFront();
            progressForm.cancel += cancelImport;
            cts = new CancellationTokenSource();
            var token = cts.Token;

            geoTagCount = 0;
            id          = 0;

            int    length = files.Length;
            Bitmap bitmap = ColorTable.getBitmap(color, 4);
            Dictionary <string, Record> recordDict = new Dictionary <string, Record>();
            var progressHandler1 = new Progress <int>(value =>
            {
                progressForm.ProgressValue = value;
                progressForm.Message       = "Import in progress, please wait... " + value.ToString() + "% completed\n" +
                                             geoTagCount + " of " + mQueueSize + " photos geotagged";
            });
            var progressValue = progressHandler1 as IProgress <int>;
            await Task.Factory.StartNew(() =>
            {
                try
                {
                    while (fileQueue.Count != 0)
                    {
                        if (token.IsCancellationRequested)
                        {
                            token.ThrowIfCancellationRequested();
                        }
                        Parallel.Invoke(
                            () =>
                        {
                            ThreadInfo threadInfo      = new ThreadInfo();
                            threadInfo.Length          = mQueueSize;
                            threadInfo.ProgressHandler = progressHandler1;
                            threadInfo.File            = fileQueue.Take();

                            Record r = null;
                            r        = readData(threadInfo);

                            MarkerTag tag     = new MarkerTag(color, id);
                            GMapMarker marker = new GMarkerGoogle(new PointLatLng(r.Latitude, r.Longitude), bitmap);
                            marker.Tag        = tag;
                            tag.Size          = 4;
                            tag.PhotoName     = r.PhotoName;
                            tag.Path          = Path.GetFullPath(r.Path);
                            overlay.Markers.Add(marker);
                        });
                    }
                }
                catch (OperationCanceledException)
                {
                    cts.Dispose();
                }
            }, cts.Token);

            progressForm.Close();
            return(overlay);
        }