William Sewell
William Sewell

Reputation: 174

How do I stop the loading bar freezing despite the task being completed?

In my code, the progress bar freezes when it reaches the "Updating portal files record..." status message. However, the subsequent task, UpdatePortalFileApprovalAsync, does actually complete successfully—I can confirm that the record updates as expected.

Oddly, everything works perfectly on our server, both in Visual Studio (debug and release modes). But when deployed to my client’s server, the task completes, yet the progress bar stops updating and appears frozen.

I'm looking for insight into why this might be happening specifically on the client’s server and how to ensure the progress bar reflects the task completion accurately.

Here's my code:

private void dateEdit_ArrivalDate_EditValueChanged(object sender, EventArgs e)
{
    if (dateEdit_ArrivalDate.EditValue != null)
        dateTimePicker_ContinuousServiceDate.Value = (DateTime)dateEdit_ArrivalDate.EditValue;
}

#region Passport

private async void button_ApprovePassport_Click(object sender, EventArgs e)
{
    await ProcessPassportPdfAsync();
}

private async Task ProcessPassportPdfAsync()
{           
    LoadingForm loadingForm = new LoadingForm();

    try
    {
        // Show loading form in a non-blocking way
        loadingForm.Show(this);
        // Start progress at 0%
        loadingForm.UpdateProgress(0);
        loadingForm.UpdateStatus("Initializing...");

        // Check if a document is selected
        if (gridView_PortalDocs.IsSelected())
        {
            var PortalDoc = gridView_PortalDocs.GetSelectedDataRow<PortalDocumentInfoModel>();

            if (PortalDoc != null)
            {
                // Validate the document before proceeding
                if (!ValidateDocumentApproval(PortalDoc))
                {
                    return; // Exit if validation fails
                }

                // Update progress to 10%
                loadingForm.UpdateProgress(10);
                loadingForm.UpdateStatus("Retrieving user signature...");

                // Get the system user info 
                var systemUserID = 345; // Replace 345 (Stefi's ID) with cGlobal.SystemUserID

                var SystemUserSignature = Controller.GetSystemUserSignature(systemUserID);

                // Check if the signature was retrieved successfully
                if (SystemUserSignature == null || SystemUserSignature.Count == 0)
                {
                    cGlobal.ShowErrorMessage("User signature not found. Please add one in Access Control.");
                    return;
                }

                // Store the user info for both stamping and approval
                var user = SystemUserSignature[0];

                // Update progress to 30%
                loadingForm.UpdateProgress(30);
                loadingForm.UpdateStatus("Fetching document...");

                EmployeePortalService EPS = new EmployeePortalService();                                            

                var Data = await EPS.GetDocument(PortalDoc.PortalFileID);

                if (Data != null && !string.IsNullOrEmpty(Data.FileData))
                {
                    // Convert base64 string to byte array
                    byte[] fileBytes = Convert.FromBase64String(Data.FileData);

                    // Update progress to 50%
                    loadingForm.UpdateProgress(50);
                    loadingForm.UpdateStatus("Stamping PDF...");

                    // Create a memory stream from the byte array
                    using (MemoryStream inputStream = new MemoryStream(fileBytes))
                    {
                        // Process the PDF (stamp it)
                        using (MemoryStream processedStream = StampPdf(inputStream, user))
                        {
                            // This is just to check the stamp is working and to make alterations.

                            // Save the processed PDF to a temporary file
                            //string tempFilePath = Path.Combine(Path.GetTempPath(), $"StampedPassport_{Guid.NewGuid()}.pdf");
                            //File.WriteAllBytes(tempFilePath, processedStream.ToArray());

                            //// Open the PDF with the default viewer
                            //System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(tempFilePath) { UseShellExecute = true });

                            // Convert the processed stream back to a base64 string
                            string processedBase64 = Convert.ToBase64String(processedStream.ToArray());

                            // Update progress to 70%
                            loadingForm.UpdateProgress(70);
                            loadingForm.UpdateStatus("Preparing stamped document...");

                            // Call the API to reupload the file with workerRefID and documentType
                            string UploadResult = await UploadStampedPdfAsync(PortalDoc, processedBase64, user.Forename, loadingForm);

                            if (UploadResult == "Success")
                            {
                                // Update progress to 100%
                                loadingForm.UpdateProgress(100);
                                loadingForm.Close();
                                loadingForm.Dispose();
                                cGlobal.ShowInfoMessage("Passport PDF processed and approved successfully.", "Success");
                            }
                            else
                            {
                                loadingForm.Close();
                                loadingForm.Dispose();
                                cGlobal.ShowErrorMessage($"Error during upload: {UploadResult}", "Upload Error");
                            }                                                                        
                        }
                    }
                }
                else
                {
                    cGlobal.ShowErrorMessage("The document data could not be retrieved from the server or is empty.");
                }

                RefreshPortalDocuments();
            }
            else
            {
                cGlobal.ShowErrorMessage("The selected document information is invalid.");
            }
        }
        else
        {
            cGlobal.ShowInfoMessage("Please select a document to process.");
        }
    }
    catch (Exception ex)
    {
        cGlobal.ShowErrorMessage($"An error occurred while processing the passport PDF: {ex.Message}");
    }
    finally
    {
        loadingForm.Close();
        loadingForm.Dispose();
    }
}

private async Task<string> UploadStampedPdfAsync(PortalDocumentInfoModel portalDoc, string base64FileContent, string approvedBy, LoadingForm loadingForm)
{
    try
    {
        using (HttpClient client = new HttpClient())
        {
            // Prepare the request URL and parameters
            string apiUrl = "Upload file api endpoitn";

            // DefaultAPIKey and JGWAPIKey in the config as well. Not sure why they gave me two keys
            string apiKey = HMEmployees.Properties.Settings.Default.DefaultAPIKey;
            string uploadUrl = $"{apiUrl}{apiKey}";

            // Create the payload
            var uploadPayload = new
            {
                workerRefID = portalDoc.WorkerReferenceID ?? 0,  // Ensure it's not null
                fileContent = base64FileContent,  // Base64 encoded file content
                documentType = portalDoc.Type  // Document type (e.g., "Hygiene")
            };

            // Serialize the payload to JSON
            string jsonPayload = JsonConvert.SerializeObject(uploadPayload);
            var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");

            loadingForm.UpdateProgress(80);
            loadingForm.UpdateStatus("Uploading stamped document...");

            // Send the POST request
            HttpResponseMessage response = await client.PostAsync(uploadUrl, content);

            if (response.IsSuccessStatusCode)
            {
                JGWService JGW = new JGWService();

                loadingForm.UpdateProgress(90);
                loadingForm.UpdateStatus("Updating portal files record...");

                // Call UpdatePortalFileApprovalAsync and check the result
                var updateResult = await JGW.UpdatePortalFileApprovalAsync(portalDoc.WorkerReferenceID ?? 0, portalDoc.Type, approvedBy);
                                        
                if (updateResult.IsSuccess) 
                {
                    // Delete the original unstamped portal file. This needs to be commented in when going live.
                    //loadingForm.UpdateProgress(95);
                    //loadingForm.UpdateStatus("Deleting original unstamped file...");
                    // await DeletePortalDocumentAsync(portalDoc);

                    return "Success";  // The upload and update were both successful
                }
                else
                {                            
                    string errorMessage = $"Update Failed: {updateResult.DetailedError ?? "No detailed error"}, {updateResult.Message ?? "No message available"}";

                    return errorMessage;
                }
            }
            else
            {
                string errorResponse = await response.Content.ReadAsStringAsync();
                string errorMessage = $"Failed: {response.StatusCode}, {errorResponse}";                       
                return errorMessage;
            }
        }
    }
    catch (Exception ex)
    {
        return $"Exception: {ex.Message}";
    }
}        

The loading form in case that's the issue:

public partial class LoadingForm : Form
{
    private Label LabelStatus;
    private ProgressBar ProgressBar;

    public LoadingForm()
    {
        InitializeComponent();
    }

    public void UpdateStatus(string status)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action(() => UpdateStatus(status)));
            return;
        }

        label_Status.Text = status;
    }

    // New method to update the progress bar value
    public async void UpdateProgress(int targetValue)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new Action(() => UpdateProgress(targetValue)));
            return;
        }

        // Start from the current progress bar value
        int currentValue = progressBar_ProgressBar.Value;

        // Increment up to the target value in small steps
        int incrementStep = 1; // Size of each step
        int delay = 20; // Delay in milliseconds between steps

        while (currentValue < targetValue)
        {
            currentValue += incrementStep;
            if (currentValue > targetValue)
            {
                currentValue = targetValue; // Ensure we don't go past the target
            }

            progressBar_ProgressBar.Value = currentValue;
            await Task.Delay(delay); // Small delay to make the increment visible
        }
    }

}

I've tried to do this:

var updateResult = await Task.Run(() => JGW.UpdatePortalFileApprovalAsync(portalDoc.WorkerReferenceID ?? 0, portalDoc.Type, approvedBy));

in case it was some kind of blocking problem but I had the same result.

Any suggestions would be appreciated.

edit: Removed actual API endpoint lol

Upvotes: 0

Views: 70

Answers (0)

Related Questions