Reputation: 332
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();
}
}
Upvotes: 2
Views: 2703
Reputation: 5990
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();
}
}
Upvotes: 4
Reputation: 3188
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();
}
Upvotes: 1
Reputation: 397
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);
}
}
Upvotes: -2
Reputation: 56
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();
}
}
Upvotes: -1