Click to See Complete Forum and Search --> : Redraw problem.


tristan202
October 1st, 2009, 06:12 AM
This is part of my code:



private void browse_button_Click(object sender, EventArgs e)
{
toolStripProgressBar1.Value = 0;
toolStripProgressBar1.Minimum = 0;
toolStripProgressBar1.Step = 1;
label_count.Text = "";
folderBrowserDialog.RootFolder = System.Environment.SpecialFolder.MyComputer;
folderBrowserDialog.ShowNewFolderButton = false;
toolStripStatusLabel1.Invalidate();
DialogResult result = folderBrowserDialog.ShowDialog();
if (result == DialogResult.OK)
{
toolStripStatusLabel1.Text = "Loading... Please wait";
toolStripStatusLabel1.Invalidate();
listbox.Items.Clear();
string foldername = folderBrowserDialog.SelectedPath;
selected_path.Text = foldername;
int count = DirCount(foldername);
toolStripProgressBar1.Maximum = count;
DirSearch(foldername);
}
else if (result == DialogResult.Cancel)
{
toolStripStatusLabel1.Text = "";
}
}

void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
DirSearch(d);
string name = d.Substring(d.LastIndexOf("\\") + 1);
{
if (name.ToLower().Contains("cd"))
{ }
else if (name.ToLower().Contains("artwork"))
{ }
else if (name.ToLower().Contains("disc"))
{ }
else if (name.ToLower().Contains("cover"))
{ }
else if (name.ToLower().Contains("label"))
{ }
else if (name.ToLower().Contains("disk"))
{ }
else
{
if (!Regex.IsMatch(name, numbers))
{
name = name.Replace("_", " ");
listbox.Items.Add(name);
toolStripProgressBar1.PerformStep();
label_count.Text = listbox.Items.Count.ToString();
label_count.Invalidate();
double percent = 100.0 * toolStripProgressBar1.Value/ toolStripProgressBar1.Maximum;
toolStripStatusLabel1.Text = ((int)percent).ToString();
toolStripStatusLabel1.Invalidate();
}
}
}
}
}
catch (System.Exception excpt)
{
MessageBox.Show(excpt.Message);
}
label_count.Text = listbox.Items.Count.ToString();
toolStripStatusLabel1.Text = "Done!";
}
int DirCount(string sDir)
{
int count = 0;
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
count += DirCount(d);
string name = d.Substring(d.LastIndexOf("\\") + 1);
{
if (name.ToLower().Contains("cd"))
{ }
else if (name.ToLower().Contains("artwork"))
{ }
else if (name.ToLower().Contains("disc"))
{ }
else if (name.ToLower().Contains("cover"))
{ }
else if (name.ToLower().Contains("label"))
{ }
else if (name.ToLower().Contains("disk"))
{ }
else
{
if (!Regex.IsMatch(name, numbers))
{
count++;
}
}
}
}
}
catch (System.Exception excpt)
{
MessageBox.Show(excpt.Message);
}
return count;
}



The problem is, that the toolStripStatusLabel1 nor the label_count don't get updated with the "Loading...Please wait", or the percentage counter during the search/count of the folders. First I had it without the Invalidate() switch, but was then suggested to add it, but that didn't help.

Any bright heads got an idea what might be wrong?

zips
October 1st, 2009, 12:53 PM
Sometimes Microsoft notoriously gives us things to use (Invalidate) and then chooses to ignore them at will. In many cases when using a loop we must resort to Application.DoEvents() to get a reasonable gui response.someloop
{
// calculate percent...
toolStripStatusLabel1.Text = Convert.ToInt32(percent).ToString();
Application.DoEvents();
}

BigEd781
October 1st, 2009, 01:04 PM
Sometimes Microsoft notoriously gives us things to use (Invalidate) and then chooses to ignore them at will. In many cases when using a loop we must resort to Application.DoEvents() to get a reasonable gui response.someloop
{
// calculate percent...
toolStripStatusLabel1.Text = Convert.ToInt32(percent).ToString();
Application.DoEvents();
}


This is bad advice. Can you show me an example where Invalidate( ) does not work? You should never have to use DoEvents( ) in a .NET application, your statement shows that you do not understand how the Windows message queue works. You should be performing your calculations in a separate thread (i.e., not the UI thread) and updating the UI by using a delegate which the secondary thread calls at fixed intervals. Take some time to look into the BackgroundWorker class.

Here is an article on the Windows message queue. Once you read that you should have a better understanding of why your redraw messages were not being processed reliably.

http://en.wikipedia.org/wiki/Microsoft_Message_Queuing

tristan202
October 1st, 2009, 01:25 PM
My initial thought was also to run the DirSearch in a seperate thread, but I haven't worked with backgroundworker before, therefore I asked.

zips
October 1st, 2009, 01:52 PM
Can you show me an example where Invalidate( ) does not work?Invalidate, Paint, Redraw, Update, etc all routinely fail to work within a tight loop - the messages are 'postponed' until Windows arrives at a 'more opportune' time. So, if the point is to update something in the gui while it is changing within a loop, Invalidate alone is useless - only the last message will be seen. Thanks for the link.

zips
October 1st, 2009, 02:13 PM
You should never have to use DoEvents( ) in a .NET application...MSDN Library for Visual Studio 2008, under Application.DoEvents Method says:Typically, you use this method in a loop to process messages.

BigEd781
October 1st, 2009, 02:33 PM
MSDN Library for Visual Studio 2008, under Application.DoEvents Method says:

It is bad practice and can lead to re-entrancy issues. I know what it is used for, but there is no reason to use it in the .NET world when it is so easy to set up a separate thread for processing.

rliq
October 1st, 2009, 09:07 PM
I believe there is only ever one WM_PAINT (and WM_TIMER) message on the Message Queue and it is always at the back of the queue.