Dynamic Label Text within a for loop

孤街醉人 提交于 2020-01-05 02:50:29

问题


I made a simple WF in C# in an attempt to change the label dynamically.

However, when I run this code, there is no visible change, until after the code has run, and then it changes to "Processing 9" 0-8 are not ever shown. Is it because it is within the loop?

 private void button1_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            label9.Text = "Processing " + i.ToString();
            Thread.Sleep(1000);
        }
    }

EDIT: X-Tech's code worked but when I tried to incorporate it into my code, I get the following threading issue. I am trying to dynamically change the label.text in the loop while the progress bar is rocking:

An exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll but was not handled in user code Additional information: Cross-thread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on. If there is a handler for this exception, the program may be safely continued

I am not sure how to attack this since I am not super familiar with Task.Factory.StartNew() and Invoke statements.

EDIT 2: Adapted Code:

 Task.Factory.StartNew(() =>
 {
      for (int i = 0; i < lstFilesToZip.Items.Count; i++)
      {
          zipArray[i] = lstFilesToZip.Items[i].ToString();
          // Report progress.
          ExecuteSecure(() => label9.Text = "Processing :" + Path.GetFileNameWithoutExtension(lstFilesToZip.Items[i].ToString()));
          ExecuteSecure(() => progressBar1.PerformStep());

          string zipFileName = Path.GetFileName(zipArray[i]);
          string newFolder = txtDestinationFolder.Text + "\\" + Path.GetFileNameWithoutExtension(zipArray[i]);
          //check to see if a directory with the file name for the zip file already exists, if not, it will create it
          if (Directory.Exists(newFolder) == false)
          {
                DirectoryInfo newPath = Directory.CreateDirectory(newFolder);
                if (lstCommonFiles.Items.Count > 0)
                {
                     //copies each file in the common file list to each new folder created, the boolean indicates that it will overwrite existing files (true) or won't (false)
                     for (int k = 0; k < lstCommonFiles.Items.Count; k++)
                     {
                          File.Copy(lstCommonFiles.Items[k].ToString(), (newFolder + "\\" + Path.GetFileName(commonArray[k])), true);
                     }
                }
                //adds the zip file into the folder as well
                File.Copy(zipArray[i], (newFolder + "\\" + zipFileName), true);

          }
    }

    if (txtCommonFiles.Text.Length <= 0)
    {
          string result = "There are no common files selected, would you still like to proceed?";
          DialogResult result1 = MessageBox.Show(result, "Common Files Missing", MessageBoxButtons.YesNo);
          if (result1 == DialogResult.No)
          {
               return;
          }
    }
    string[] dirs = Directory.GetDirectories(txtDestinationFolder.Text);

    // Grabs the folders in the newly created directory
    foreach (string dir in dirs)
          lstDestinationFinal.Items.Add(dir);

    //send sample file contents to preview window
    string[] sampleFiles = Directory.GetFiles(lstDestinationFinal.Items[0].ToString());

    //grabs the files
    foreach (string zipFiles in sampleFiles)
         lstSampleFile.Items.Add(zipFiles);

    ExecuteSecure(() =>tabControl1.SelectedTab = tabPage2);
});

}

And the added Method:

 private void ExecuteSecure(Action action)
    {
        if (InvokeRequired)
        {
            Invoke(new MethodInvoker(() => action()));
        }
        else
        {
            action();
        }
    }

回答1:


Try this

Task.Factory.StartNew(() =>
{
     for (int i = 0; i < 10; i++)
     {              
          Invoke(new MethodInvoker(() => label9.Text = "Processing " + i.ToString()));
          Thread.Sleep(1000);
     }
});

EDIT:

Task.Factory.StartNew(() =>
{
     for (int i = 0; i < 10; i++)
     {
          // Any GUI control which you want to use within thread,
          // you need Invoke using GUI thread. I have declare a method below for this
          //Now use this method as
          ExecuteSecure(() => label9.Text = "Processing " + i);
          ExecuteSecure(() => progressBar1.Value = i * 10);
          //... other code etc.
          Thread.Sleep(1000);
     }
});


//---
private void ExecuteSecure(Action action)
{
    if (InvokeRequired)
    {
        Invoke(new MethodInvoker(() => action()));
    }
    else
    {
        action();
    }
}



回答2:


Use a BackgroundWorker if you want your UI to be updated in real time, else all the work is done on the UI thread and it remains frozen until the work is over.

private void button1_Click(object sender, EventArgs e)
    {
        int limit = 10;
        var bw = new BackgroundWorker();
        bw.WorkerReportsProgress = true;
        bw.DoWork += (s, ee) =>
        {
            for (int i = 0; i < limit; i++)
            {
                bw.ReportProgress(i);
                Thread.Sleep(1000);
            }
        };
        bw.ProgressChanged += (s, ee) => label9.Text = "Processing" + ee.ProgressPercentage.ToString();
        bw.RunWorkerAsync();
    }



回答3:


Maybe try

 private void button1_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 10; i++)
    {
        label9.Text = "Processing " + i.ToString();
        Thread.Sleep(1000);
        Form1.Refresh();
    }
}



回答4:


Try this:

private void button1_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            label9.Text = "Processing " + i.ToString();
            Application.DoEvents();
            Thread.Sleep(1000);
        }
    }


来源:https://stackoverflow.com/questions/32012376/dynamic-label-text-within-a-for-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!