public void Start()
        {
            string PrintName = string.Empty;
            int    Width     = 70;

            try
            {
                if (Error)
                {
                    Close();
                    return;
                }

                // First thing: build a file list.
                StatusString = "Getting volume bitmap";
                if (!Volume.GetBitmap())
                {
                    StatusString = "Could not get volume " + DriveName + " bitmap";
                    Error        = true;
                    Close();
                    return;
                }

                UpdateDrawing = true;

                _lastBMPUpdate = DateTime.Now;

                if (PleaseStop)
                {
                    Close();
                    return;
                }

                StatusString = "Obtaining volume geometry";
                if (!Volume.PartInfo.GetPartitionInfo())
                {
                    StatusString = "Could not obtain volume " + DriveName + " geometry";
                    Error        = true;

                    Close();

                    return;
                }

                if (PleaseStop)
                {
                    Close();
                    return;
                }

                StatusString = "Obtaining partition information";
                if (!Volume.PartInfo.GetPartitionDetails())
                {
                    StatusString = "Could not obtain partition " + DriveName + " information";
                    Error        = true;

                    Close();

                    return;
                }

                if (PleaseStop)
                {
                    Close();
                    return;
                }

                StatusString = "Building file database for volume " + DriveName;
                if (!Volume.BuildFileList(this))
                {
                    StatusString = "Could not build file database for volume " + DriveName;
                    Error        = true;
                    Close();
                    return;
                }

                if (PleaseStop)
                {
                    Close();
                    return;
                }

                StatusString = "Analyzing database for " + DriveName;
                UInt64 TotalClusters = 0;
                uint   i;
                for (i = 0; i < Volume.DBFileCount; i++)
                {
                    TotalClusters += Volume.GetDBFile(i).Clusters;
                }

                // Defragment!
                UInt64 ClustersProgress = 0;

                // Find first free LCN for speedier searches ...
                UInt64 FirstFreeLCN;
                Volume.FindFreeRange(0, 1, out FirstFreeLCN);

                if (PleaseStop)
                {
                    Close();
                    return;
                }

                // Analyze?
                if (DefragType == DefragMethod.ANALYZE)
                {
                    uint j;

                    Report.RootPath     = Volume.RootPath;
                    Report.Label        = Volume.PartInfo.Name;
                    Report.Serial       = Volume.PartInfo.Serial;
                    Report.FileSystem   = Volume.PartInfo.FileSystem;
                    Report.FreeBytes    = Volume.PartInfo.FreeBytes;
                    Report.ClusterCount = Volume.PartInfo.ClusterCount;
                    Report.ClusterSize  = Volume.PartInfo.ClusterSize;

                    Report.FraggedFiles.Clear();
                    Report.UnfraggedFiles.Clear();
                    Report.UnmovableFiles.Clear();

                    Report.FilesCount    = (ulong)Volume.DBFileCount - (ulong)Volume.DBDirCount;
                    Report.DirsCount     = (ulong)Volume.DBDirCount;
                    Report.DiskSizeBytes = Volume.PartInfo.TotalBytes;

                    Report.FilesSizeClusters = 0;
                    Report.FilesSlackBytes   = 0;
                    Report.FilesSizeBytes    = 0;
                    Report.FilesFragments    = 0;

                    for (j = 0; j < Volume.DBFileCount; j++)
                    {
                        var Info = Volume.GetDBFile(j);

                        Report.FilesFragments += (uint)Utils.Max(1UL, (ulong)Info.Fragments.Count); // add 1 fragment even for 0 bytes/0 cluster files

                        if (!Info.Attributes.Process)
                        {
                            continue;
                        }

                        StatusString = Volume.GetDBDir(Info.DirIndice) + Info.Name;

                        Report.FilesSizeClusters += Info.Clusters;
                        Report.FilesSizeBytes    += Info.Size;

                        if (Info.Attributes.Unmovable)
                        {
                            Report.UnmovableFiles.Add(j);
                        }

                        if (Info.Fragments.Count > 1)
                        {
                            Report.FraggedFiles.Add(j);
                        }
                        else
                        {
                            Report.UnfraggedFiles.Add(j);
                        }

                        StatusPercent = (j / (double)Report.FilesCount) * 100.0f;
                    }

                    Report.FilesSizeOnDisk = Report.FilesSizeClusters * Volume.PartInfo.ClusterSize;
                    Report.FilesSlackBytes = Report.FilesSizeOnDisk - Report.FilesSizeBytes;
                    Report.PercentFragged  = 100.0f * (Report.FraggedFiles.Count / (double)Report.FilesCount);

                    var Percent = (10000 * Report.FilesSlackBytes) / Report.FilesSizeOnDisk;
                    Report.PercentSlack = (double)Percent / 100.0f;
                }
                else
                {
                    // Go through all the files and ... defragment them!
                    for (i = 0; i < Volume.DBFileCount; i++)
                    {
                        // What? They want us to pause? Oh ok.
                        if (PleasePause)
                        {
                            StatusString = "Paused";
                            PleasePause  = false;

                            while (PleasePause == false)
                            {
                                Thread.Sleep(50);
                            }

                            PleasePause = false;
                        }

                        if (PleaseStop)
                        {
                            StatusString = "Stopping";
                            break;
                        }

                        //
                        var Info = Volume.GetDBFile(i);

                        var PreviousClusters = ClustersProgress;
                        ClustersProgress += Info.Clusters;

                        if (!Info.Attributes.Process)
                        {
                            continue;
                        }

                        if (!DoLimitLength)
                        {
                            StatusString = Volume.GetDBDir(Info.DirIndice) + Info.Name;
                        }
                        else
                        {
                            PrintName    = Utils.FitName(Volume.GetDBDir(Info.DirIndice), Info.Name, Width);
                            StatusString = PrintName;
                        }

                        // Calculate percentage complete
                        StatusPercent = 100.0f * (PreviousClusters / (double)TotalClusters);

                        // Can't defrag directories yet
                        if (Info.Attributes.Directory)
                        {
                            continue;
                        }

                        // Can't defrag 0 byte files :)
                        if (Info.Fragments.Count == 0)
                        {
                            continue;
                        }

                        // If doing fast defrag, skip non-fragmented files
                        // Note: This assumes that the extents stored in Info.Fragments
                        //       are consolidated. I.e. we assume it is NOT the case that
                        //       two extents account for a sequential range of (non-
                        //       fragmented) clusters.
                        if (Info.Fragments.Count == 1 && DefragType == DefragMethod.FASTDEFRAG)
                        {
                            continue;
                        }

                        // Otherwise, defrag0rize it!
                        int Retry = 3;  // retry a few times
                        while (Retry > 0)
                        {
                            // Find a place that can fit the file
                            UInt64 TargetLCN;
                            var    Result = Volume.FindFreeRange(FirstFreeLCN, Info.Clusters, out TargetLCN);

                            // If yes, try moving it
                            if (Result)
                            {
                                // If we're doing an extensive defrag and the file is already defragmented
                                // and if its new location would be after its current location, don't
                                // move it.
                                if (DefragType == DefragMethod.NORMDEFRAG && Info.Fragments.Count == 1 && TargetLCN > Info.Fragments[0].StartLCN)
                                {
                                    Retry = 1;
                                }
                                else
                                {
                                    if (Volume.MoveFileDumb((int)i, TargetLCN))
                                    {
                                        Retry = 1; // yay, all done with this file.
                                        Volume.FindFreeRange(0, 1, out FirstFreeLCN);
                                    }
                                }
                            }

                            // Only update bitmap if it's older than 15 seconds
                            if (DateTime.Now.Subtract(_lastBMPUpdate).TotalSeconds < 15000)
                            {
                                Retry = 1;
                            }
                            else
                            if (!Result || Retry != 1)
                            {   // hmm. Wait for a moment, then update the drive bitmap
                                //SetStatusString (L"(Reobtaining volume " + DriveName + L" bitmap)");

                                if (!DoLimitLength)
                                {
                                    StatusString += " .";
                                }

                                if (Volume.GetBitmap())
                                {
                                    _lastBMPUpdate = DateTime.Now;

                                    if (!DoLimitLength)
                                    {
                                        StatusString = Volume.GetDBDir(Info.DirIndice) + Info.Name;
                                    }
                                    else
                                    {
                                        StatusString = PrintName;
                                    }

                                    Volume.FindFreeRange(0, 1, out FirstFreeLCN);
                                }
                                else
                                {
                                    StatusString = "Could not re-obtain volume " + DriveName + " bitmap";
                                    Error        = true;
                                }
                            }

                            Retry--;
                        }

                        if (Error)
                        {
                            break;
                        }
                    }
                }
            }
            catch (ThreadAbortException)
            {
            }
            finally
            {
                Close();
            }
        }