none
Display thread progress RRS feed

  • Question

  • I not sure if this will make sense or not but I want to display a counter/progress of a separate task running.

    Here is my function:

    private DataTable CreateAHApwTable()
            {
                try
                {
                    DataTable dt = new DataTable();
                    int ID = 0;
    
                    dt.Clear();
                    dt.Columns.Add("ID");
                    dt.Columns.Add("AHApw_Input");
                    dt.Columns.Add("AHA_ID");
                    dt.Columns.Add("AHApw");
                    dt.Columns.Add("Email");
    
                    foreach (DataGridViewRow row in dgvAHApwImportList.Rows)
                    {
                        string ahaid = row.Cells["avectraId"].Value.ToString();
                        string email = row.Cells["email"].Value.ToString();
                        string ahapw_input = row.Cells["ahapw_input"].Value.ToString();
                        string AHApw = CryptoUtils.Encrypt(ahapw_input, "C3BC4902-A043-4A61-B51D-603DABA62575");
    
                        ID++;
                        dt.Rows.Add(ID.ToString(), ahapw_input, ahaid, AHApw, email);
                        tbAhapwDisplay.Text = "Processed " + ID.ToString();
                    }
    
                    return dt;
                }
                catch(Exception ex)
                {
                    return null;
                }
            }

    Pretty basic except I throw an error because I'm trying to access an outside thread. I know the issue its because I want to update my textbox. So how would I update my textbox text without throwing an error?

    Task Code:

    tbAhapwDisplay.Text = "Processing Please Wait ...";
                        DataTable oDS = new DataTable();
    
                        Task taskB = Task.Factory.StartNew(() => oDS = CreateAHApwTable());
                        taskB.Wait();
    
                        dgvAHApwExportList.DataSource = oDS;
                        tbAhapwDisplay.Text = "Processed " + dgvAHApwExportList.Rows.Count.ToString() + " Records";

    I would like some kind of progress displayed or returned while its processing. Suggestions? I can do it without splitting it into a task but I'd like some kind of progress display.

    Monday, January 29, 2018 8:33 PM

Answers

  • I switched it over to a background worker and I just allow update on the worker.

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                e.Result = CreateAHApwTable();
            }
    
            private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                try
                {
                    string Progress = e.ProgressPercentage.ToString();
    
                    this.tbAhapwDisplay.Text = @"Processing Record: " + Progress;
                }
                catch(Exception ex)
                {
    
                }            
            }

    also switched it over to build a data table instead of directly adding a row to the data grid viewer.


     private DataTable CreateAHApwTable()
            {
                try
                {
                    DataTable dt = new DataTable();
                    int ID = 0;
    
                    dt.Clear();
                    dt.Columns.Add("ID");
                    dt.Columns.Add("AHApw_Input");
                    dt.Columns.Add("AHA_ID");
                    dt.Columns.Add("AHApw");
                    dt.Columns.Add("Email");
    
                    foreach (DataGridViewRow row in dgvAHApwImportList.Rows)
                    {
                        string ahaid = row.Cells["avectraId"].Value.ToString();
                        string email = row.Cells["email"].Value.ToString();
                        string ahapw_input = row.Cells["ahapw_input"].Value.ToString();
                        string AHApw = CryptoUtils.Encrypt(ahapw_input, "C3BC4902-A043-4A61-B51D-603DABA62575");
    
                        ID++;
                        dt.Rows.Add(ID.ToString(), ahapw_input, ahaid, AHApw, email);
                        backgroundWorker1.ReportProgress(ID);
                    }
    
                    return dt;
                }
                catch(Exception ex)
                {
                    return null;
                }
            }

    • Marked as answer by old_School Monday, January 29, 2018 10:39 PM
    • Edited by old_School Monday, January 29, 2018 10:39 PM
    Monday, January 29, 2018 10:39 PM

All replies

  • If it is a Winforms application, you transfer execution to the main thread when you want to display progress. This can be done by means of the Invoke method of any control:

    tbAhapwDisplay.Invoke(new MethodInvoker( () =>
        tbAhapwDisplay.Text = "Processed " + dgvAHApwExportList.Rows.Count.ToString() + " Records" ));

    The argument to Invoke is a delegate that points to the code that you want to execute in the main thread. In this example I used a lambda expression to initialize the delegate, but you may of course do it in a different way if you prefer so.

    Monday, January 29, 2018 9:55 PM
    Moderator
  • I switched it over to a background worker and I just allow update on the worker.

     private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                e.Result = CreateAHApwTable();
            }
    
            private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                try
                {
                    string Progress = e.ProgressPercentage.ToString();
    
                    this.tbAhapwDisplay.Text = @"Processing Record: " + Progress;
                }
                catch(Exception ex)
                {
    
                }            
            }

    also switched it over to build a data table instead of directly adding a row to the data grid viewer.


     private DataTable CreateAHApwTable()
            {
                try
                {
                    DataTable dt = new DataTable();
                    int ID = 0;
    
                    dt.Clear();
                    dt.Columns.Add("ID");
                    dt.Columns.Add("AHApw_Input");
                    dt.Columns.Add("AHA_ID");
                    dt.Columns.Add("AHApw");
                    dt.Columns.Add("Email");
    
                    foreach (DataGridViewRow row in dgvAHApwImportList.Rows)
                    {
                        string ahaid = row.Cells["avectraId"].Value.ToString();
                        string email = row.Cells["email"].Value.ToString();
                        string ahapw_input = row.Cells["ahapw_input"].Value.ToString();
                        string AHApw = CryptoUtils.Encrypt(ahapw_input, "C3BC4902-A043-4A61-B51D-603DABA62575");
    
                        ID++;
                        dt.Rows.Add(ID.ToString(), ahapw_input, ahaid, AHApw, email);
                        backgroundWorker1.ReportProgress(ID);
                    }
    
                    return dt;
                }
                catch(Exception ex)
                {
                    return null;
                }
            }

    • Marked as answer by old_School Monday, January 29, 2018 10:39 PM
    • Edited by old_School Monday, January 29, 2018 10:39 PM
    Monday, January 29, 2018 10:39 PM
  • For the future note that this is not a C# question. We are assuming this is a Windows Forms application and if that is correct then the Windows Forms forum would be the place.

    The BackgroundWorker was designed for this. The methods of the BackgroundWorker execute in a separate thread except the ReportProgress executes in the UI thread so the switch is done for you automatically.



    Sam Hobbs
    SimpleSamples.Info

    Monday, January 29, 2018 10:48 PM