private async Task PingService()
        {
            cmdApply.Enabled  = false;
            tsBtnPing.Enabled = false;
            StatusMsg("Pinging ( connection and authorization test )....");
            APIConnector = new Cloud_Elements_API.CloudElementsConnector();
            APIConnector.APIAuthorization = APIAuthorization;
            APIConnector.DiagTrace       += new Cloud_Elements_API.CloudElementsConnector.DiagTraceEventHanlder(HandleDiagEvent);
            Boolean result = false;

            try
            {
                Cloud_Elements_API.Pong PongResult = await APIConnector.Ping();

                // here is one of the few example where we really go async within a single method...
                Task <Cloud_Elements_API.CloudStorage> StorageTask = APIConnector.GetStorageAvailable();
                StatusMsg(PongResult.ToString());
                UpdateSecretsFile(PongResult.ToString());
                if (APIConnector.EndpointOptions.HasExtraHeader)
                {
                    APIConnector.EndpointOptions.SetExtraHeaderValue(APIAuthorization.ExtraValue);
                }
                toolStripTxtConnectionNow.Text = PongResult.endpoint;
                try
                {
                    Cloud_Elements_API.CloudStorage StorageResult = await StorageTask;
                    StatusMsg(string.Format("Storage - Total {0}; Shared {1}; Used {2}", Cloud_Elements_API.Tools.SizeInBytesToString(StorageResult.total),
                                            Cloud_Elements_API.Tools.SizeInBytesToString(StorageResult.shared),
                                            Cloud_Elements_API.Tools.SizeInBytesToString(StorageResult.used)));
                }
                catch (Exception ex)
                {
                    StatusMsg("Storge check failed: " + ex.Message);
                }

                result = true;
            }
            catch (Exception ex)
            {
                StatusMsg("Failed: " + ex.Message);
            }
            finally
            {
                cmdApply.Enabled = true;
                UIState(result);
            }
        }
        async Task <string> TestAsyncGetFileMeta()
        {
            string tfoldername = AsyncBasePath; // as set at start of tests

            System.Collections.Generic.Queue <Task <Cloud_Elements_API.CloudFile> >     MetaTasks      = new System.Collections.Generic.Queue <Task <Cloud_Elements_API.CloudFile> >();
            System.Collections.Generic.List <Cloud_Elements_API.CloudElementsConnector> ConnectorsUsed = new System.Collections.Generic.List <Cloud_Elements_API.CloudElementsConnector>();
            DateTime Started   = DateTime.Now;
            int      MetaCount = 0;

            for (int rr = 1; rr <= 4; rr++)
            {
                for (int i = 1; i <= 16; i++)
                {
                    string TargetPath = tfoldername + string.Format("/SFCE_test_file_{0}.txt", i);
                    Cloud_Elements_API.CloudElementsConnector ViaConnector = null;
                    ViaConnector = APIConnector.Clone();
                    Task <Cloud_Elements_API.CloudFile> OneMeta = Cloud_Elements_API.FileOperations.GetCloudFileInfo(ViaConnector, Cloud_Elements_API.CloudElementsConnector.FileSpecificationType.Path, TargetPath);
                    ConnectorsUsed.Add(ViaConnector);
                    MetaTasks.Enqueue(OneMeta);
                    if (SerializeGetFileMetadataRequests)
                    {
                        OneMeta.Wait();
                    }
                    MetaCount += 1;
                }
            }

            int rewaitCnt = 0;

            System.Text.StringBuilder Summary = new System.Text.StringBuilder();
            while (MetaTasks.Count > 0)
            {
                Task <Cloud_Elements_API.CloudFile> AnUpload = MetaTasks.Dequeue();

                if (AnUpload.GetAwaiter().IsCompleted)
                {
                    try
                    {
                        Cloud_Elements_API.CloudFile Result = await AnUpload;
                        if (Result != null)
                        {
                            Summary.AppendFormat("\t{5}: Task {2} File Info for {0}, id={1}, ok={3} \r\n", Result.name, Result.id, AnUpload.Id, !AnUpload.IsFaulted,
                                                 0, Cloud_Elements_API.Tools.TraceTimeNow());
                        }
                        else
                        {
                            Summary.AppendFormat("\t{5}: Task {2} did not obtain file Info for {0}, id={1}, ok={3} \r\n", "", "", AnUpload.Id, !AnUpload.IsFaulted,
                                                 0, Cloud_Elements_API.Tools.TraceTimeNow());
                        }
                    }
                    catch (Exception ex)
                    {
                        Summary.AppendFormat("\t{5}: Task {2} File Info Exception {0}, ok={3} \r\n", ex.Message, 0, AnUpload.Id, !AnUpload.IsFaulted,
                                             0, Cloud_Elements_API.Tools.TraceTimeNow());
                    }
                }
                else
                {
                    //   if (AnUpload.Status == TaskStatus.WaitingForActivation) AnUpload.ci
                    MetaTasks.Enqueue(AnUpload);
                    rewaitCnt += 1;
                    System.Threading.Thread.Sleep(128);
                }
            }

            foreach (Cloud_Elements_API.CloudElementsConnector ViaConnector in ConnectorsUsed)
            {
                ViaConnector.Close();
            }
            ConnectorsUsed.Clear();

            Summary.AppendFormat("\t{0}: Finished \r\n", Cloud_Elements_API.Tools.TraceTimeNow());
            double RequiredMS = DateTime.Now.Subtract(Started).TotalMilliseconds;

            Summary.Insert(0, string.Format("Got {0} file infos in {1:F2}s, average {2:F2}s / file; Async Waits: {3} \r\n", MetaCount, RequiredMS / 1000d, RequiredMS / (1000d * MetaCount),
                                            rewaitCnt, 0));
            return(Summary.ToString());
        }
        async Task <string> TestMultiFileAsyncUploads()
        {
            string tfoldername = AsyncBasePath; // set at start of tests

            System.Collections.Generic.Queue <Task <Cloud_Elements_API.CloudFile> >     UploadTasks    = new System.Collections.Generic.Queue <Task <Cloud_Elements_API.CloudFile> >();
            System.Collections.Generic.List <Cloud_Elements_API.CloudElementsConnector> ConnectorsUsed = new System.Collections.Generic.List <Cloud_Elements_API.CloudElementsConnector>();


            DateTime Started     = DateTime.Now;
            int      uploadCount = 0;

            System.IO.Stream teststream;
            string           RandomContent = GenerateRandomContent(256 * 1024 * 8);

            if (NumberOfFilesAlreadyUploaded == 0)
            {
                DownloadTestExpectedHash = RandomContent.GetHashCode();
            }
            long TotalBytes = 0;

            for (int i = 1; i <= 8; i++)
            {
                teststream    = GenerateStreamFromString(RandomContent);
                RandomContent = RandomContent.Substring(RandomContent.Length / 2);
                string        MIMEType    = Cloud_Elements_API.Tools.FileTypeToMimeContentType("txt");
                List <String> TagList     = new List <String>();
                long          sizeInBytes = teststream.Length;
                TotalBytes += sizeInBytes;
                string TargetPath = tfoldername + string.Format("/SFCE_test_file_{0}.txt", i + NumberOfFilesAlreadyUploaded);
                Cloud_Elements_API.CloudElementsConnector ViaConnector = APIConnector.Clone();
                ConnectorsUsed.Add(ViaConnector);
                Task <Cloud_Elements_API.CloudFile> AnUpload = ViaConnector.PostFile(teststream, MIMEType,
                                                                                     TargetPath, "Temporary test file",
                                                                                     TagList.ToArray(), false, sizeInBytes);
                //System.Runtime.CompilerServices.ConfiguredTaskAwaitable<Cloud_Elements_API.CloudFile> AwaitableUpload;
                //AwaitableUpload                  =    AnUpload.ConfigureAwait(false);

                UploadTasks.Enqueue(AnUpload);
                uploadCount += 1;
            }

            int rewaitCnt = 0;

            System.Text.StringBuilder Summary = new System.Text.StringBuilder();
            while (UploadTasks.Count > 0)
            {
                Task <Cloud_Elements_API.CloudFile> AnUpload = UploadTasks.Dequeue();

                if (AnUpload.GetAwaiter().IsCompleted)
                {
                    try
                    {
                        Cloud_Elements_API.CloudFile Result = await AnUpload;
                        Summary.AppendFormat("\t{5}: Task {2} Uploaded {4:F1}KB to {0}, id={1}, ok={3} \r\n", Result.name, Result.id, AnUpload.Id, !AnUpload.IsFaulted,
                                             Result.size / 1024d, Cloud_Elements_API.Tools.TraceTimeNow());
                    }
                    catch (Exception ex)
                    {
                        Summary.AppendFormat("\t{5}: Task {2} Upload Exception {0}, ok={3} \r\n", ex.Message, 0, AnUpload.Id, !AnUpload.IsFaulted,
                                             0, Cloud_Elements_API.Tools.TraceTimeNow());
                    }
                }
                else
                {
                    //   if (AnUpload.Status == TaskStatus.WaitingForActivation) AnUpload.ci
                    UploadTasks.Enqueue(AnUpload);
                    rewaitCnt += 1;
                    System.Threading.Thread.Sleep(128);
                }
            }

            foreach (Cloud_Elements_API.CloudElementsConnector ViaConnector in ConnectorsUsed)
            {
                ViaConnector.Close();
            }
            ConnectorsUsed.Clear();

            Summary.AppendFormat("\t{0}: Finished \r\n", Cloud_Elements_API.Tools.TraceTimeNow());
            double RequiredMS = DateTime.Now.Subtract(Started).TotalMilliseconds;

            Summary.Insert(0, string.Format("Uploaded {0} files in {1:F2}s, average {2:F2}s / file, {4:F2}ms/KB; Async Waits: {3} \r\n", uploadCount, RequiredMS / 1000d, RequiredMS / (1000d * uploadCount),
                                            rewaitCnt, (RequiredMS) / (TotalBytes / 1024d)));
            return(Summary.ToString());
        }
        private async Task <bool> scanForEmptyFolders(EmptyFolderOptions scanOptions, Cloud_Elements_API.CloudFile currentRow)
        {
            //StatusMsg(string.Format("Scanning folder {0}", currentRow.name));
            Cloud_Elements_API.CloudElementsConnector ViaConnector = APIConnector.Clone();
            bool deletedAnything = false;

            try
            {
                if (currentRow.directory)
                {
                    List <Cloud_Elements_API.CloudFile> ResultList = null;
                    if (currentRow.size > 0)
                    {
                        ResultList = await ViaConnector.ListFolderContents(Cloud_Elements_API.CloudElementsConnector.FileSpecificationType.Path, currentRow.path, chkWithTags.Checked);

                        TestStatusMsg(string.Format("FYI: Folder {1} contains {0} bytes in file(s)", currentRow.size, currentRow.path));

                        for (int i = 0; i < ResultList.Count; i++)
                        {
                            if (ResultList[i].directory)
                            {
                                deletedAnything = await scanForEmptyFolders(scanOptions, ResultList[i]);
                            }
                        }
                    }


                    // if anything was deleted by our recursive calls, we need to re-get the result list!
                    if (deletedAnything)
                    {
                        ResultList = await ViaConnector.ListFolderContents(Cloud_Elements_API.CloudElementsConnector.FileSpecificationType.Path, currentRow.path, chkWithTags.Checked);

                        //TestStatusMsg(string.Format("FYI: Folder {1} now contains {0} bytes", currentRow.size, currentRow.path));
                        if (ResultList.Count > 1)
                        {
                            return(deletedAnything);
                        }
                    }

                    if ((currentRow.size > 0) && (scanOptions.SingleFileOK) && (ResultList.Count == 1) && !ResultList[0].directory)
                    {
                        double fileAge = -1;
                        if (ResultList[0].IsCreatedValid)
                        {
                            fileAge = DateTime.Now.Subtract(ResultList[0].WhenCreated()).TotalHours;
                        }
                        if ((ResultList[0].size <= scanOptions.SingleFileSizeUnder) &&
                            (!scanOptions.SingleFileTagRequired || ResultList[0].HasTags) &&
                            (ResultList[0].IsCreatedValid && (fileAge >= scanOptions.SingleFileAgeInHours)) &&
                            (ResultList[0].path.EndsWith(scanOptions.SingleFileType, StringComparison.CurrentCultureIgnoreCase)))
                        {
                            // single file is ok to ignored (removed message from here)
                        }
                        else
                        {
                            TestStatusMsg(string.Format("Kept {0} - folder contains {1}, {2} bytes; {3:F1} hours old", currentRow.path, ResultList[0].name, ResultList[0].size, fileAge));
                            return(deletedAnything);
                        }
                    }

                    if ((scanOptions.PathCheck) && (currentRow.path.IndexOf(scanOptions.PathMustContain, StringComparison.CurrentCultureIgnoreCase) < 0))
                    {
                        TestStatusMsg(string.Format("Kept {0} - folder path does not contain {1}", currentRow.path, scanOptions.PathMustContain));
                        return(deletedAnything);
                    }

                    TestStatusMsg(string.Format("Deleting {0}; (empty)", currentRow.path));
                    StatusMsg(string.Format("Deleting {0}, size={1}", currentRow.path, Cloud_Elements_API.Tools.SizeInBytesToString(currentRow.size)));
                    deletedAnything = await ViaConnector.DeleteFolder(Cloud_Elements_API.CloudElementsConnector.FileSpecificationType.Path, currentRow.path, false);

                    CountOfFoldersRemoved++;
                }
            }
            catch (Exception exep)
            {
                StatusMsg(string.Format("Problem! {0}", exep));
            }

            ViaConnector.Close();
            return(deletedAnything);
        }