Timer.Tick event not firing

J

Jason

I have an application that uses a timer. I've created a function
called TickEvent that I "assigned" to the timer1.Tick event:

this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.TickEvent);
....
private void TickEvent(object sender, System.EventArgs e)
{
liSecondsElapsed++;
DateTime lsTime = Convert.ToDateTime(liSecondsElapsed);
lblTimer.Text = lsTime.Hour.ToString() + ":" +
lsTime.Minute.ToString() + ":" + lsTime.Second.ToString();
lblTimer.Refresh();
}

In my main click event, I have the following:

private void miGetAceMap_Click(object sender, System.EventArgs e)
{
lsCurrentFolderPath = lsRootFolderPath;
txtOutput.Visible = true;

ThreadStart timerWorker = new ThreadStart(Start_Timer);
Thread tTimer = new Thread(timerWorker);
tTimer.Start();

ThreadStart worker = new ThreadStart(Get_Folders_Simple);
Thread t = new Thread(worker);
t.Start();

t.Join();
tTimer.Join();
timer1.Stop();
this.lblStatus.Text = "Complete";
liFolderCounter--;
lblFolderCount.Text = "Found " + liFolderCounter.ToString() + "
folders";
}

private void Start_Timer()
{
timer1.Enabled = true;
timer1.Start();
}

My TickEvent doesn't ever seem to fire because the elapsed time is
never displayed in the lblTimer label.

Can someone please help???

Thanks!
 
W

Willy Denoyette [MVP]

Jason said:
I have an application that uses a timer. I've created a function
called TickEvent that I "assigned" to the timer1.Tick event:

this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.TickEvent);
...
private void TickEvent(object sender, System.EventArgs e)
{
liSecondsElapsed++;
DateTime lsTime = Convert.ToDateTime(liSecondsElapsed);
lblTimer.Text = lsTime.Hour.ToString() + ":" +
lsTime.Minute.ToString() + ":" + lsTime.Second.ToString();
lblTimer.Refresh();
}

In my main click event, I have the following:

private void miGetAceMap_Click(object sender, System.EventArgs e)
{
lsCurrentFolderPath = lsRootFolderPath;
txtOutput.Visible = true;

ThreadStart timerWorker = new ThreadStart(Start_Timer);
Thread tTimer = new Thread(timerWorker);
tTimer.Start();

ThreadStart worker = new ThreadStart(Get_Folders_Simple);
Thread t = new Thread(worker);
t.Start();

t.Join();
tTimer.Join();
timer1.Stop();
this.lblStatus.Text = "Complete";
liFolderCounter--;
lblFolderCount.Text = "Found " + liFolderCounter.ToString() + "
folders";
}

private void Start_Timer()
{
timer1.Enabled = true;
timer1.Start();
}

My TickEvent doesn't ever seem to fire because the elapsed time is
never displayed in the lblTimer label.

Can someone please help???

Thanks!

What are you doing in Get_Folders_Simple?
Is it possible that this thread procedure retuns before the timer expires?
I see no reason to start a timer using a thread, threads are expensive
resources you know!

Willy.
 
J

Jason

Well, I just learned how to use threads, so I thought why not...

This is also my first time with the Timer control. I thought the
instance of the timer ran until you manually stopped it?

Anyway, this is the Get_Folder_Simple function. It's recursive and
finds all of the NTFS permissions of a given folder and all of it's
subfolders. Then it places all of the NTFS information into a typed
DataSet that can be exported to XML.

private void Get_Folders_Simple()
{
txtOutput.Text += lsCurrentFolderPath + System.Environment.NewLine;
string[] laSplit = lsCurrentFolderPath.Split('\\');
string lsName = laSplit[laSplit.GetUpperBound(0)];

DataRow loDRsubDirectory = dsDirectory.Tables[0].NewRow();
loDRsubDirectory["ID"] = liFolderCounter;
loDRsubDirectory["Name"] = lsName;
loDRsubDirectory["Path"] = lsCurrentFolderPath;
dsDirectory.Tables[0].Rows.Add(loDRsubDirectory);

string lsString = lsCurrentFolderPath.Replace(@"\", @"\\");
ManagementObject lfs = new
ManagementObject(@"Win32_LogicalFileSecuritySetting.Path='" + lsString
+ "'");

ManagementBaseObject outP = lfs.InvokeMethod("GetSecurityDescriptor",
null, null);
if (((uint)(outP.Properties["ReturnValue"].Value)) == 0)
{
ManagementBaseObject Descriptor =
((ManagementBaseObject)(outP.Properties["Descriptor"].Value));
ManagementBaseObject[] DaclObject =
((ManagementBaseObject[])(Descriptor.Properties["Dacl"].Value));
DumpACEs(DaclObject);
}
liFolderCounter++;

DirectoryInfo d = new DirectoryInfo(lsCurrentFolderPath);
DirectoryInfo[] dis = d.GetDirectories();
foreach(DirectoryInfo di in dis)
{
try
{
lsCurrentFolderPath = di.FullName.ToString();

this.lblStatusLabel.Text = "Enumerating folder: ";
this.lblStatusLabel.Refresh();
this.lblStatus.Text = lsCurrentFolderPath;
this.lblStatus.Refresh();
Get_Folders_Simple();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error parsing folder " +
lsCurrentFolderPath);
this.Close();
}
}
}
 
J

Jason

Also, I've tried enabling and starting the timer in the main thread and
it still doesn't seem to work.
 
W

Willy Denoyette [MVP]

Jason said:
Well, I just learned how to use threads, so I thought why not...

This is also my first time with the Timer control. I thought the
instance of the timer ran until you manually stopped it?

Anyway, this is the Get_Folder_Simple function. It's recursive and
finds all of the NTFS permissions of a given folder and all of it's
subfolders. Then it places all of the NTFS information into a typed
DataSet that can be exported to XML.

private void Get_Folders_Simple()
{
txtOutput.Text += lsCurrentFolderPath + System.Environment.NewLine;
string[] laSplit = lsCurrentFolderPath.Split('\\');
string lsName = laSplit[laSplit.GetUpperBound(0)];

DataRow loDRsubDirectory = dsDirectory.Tables[0].NewRow();
loDRsubDirectory["ID"] = liFolderCounter;
loDRsubDirectory["Name"] = lsName;
loDRsubDirectory["Path"] = lsCurrentFolderPath;
dsDirectory.Tables[0].Rows.Add(loDRsubDirectory);

string lsString = lsCurrentFolderPath.Replace(@"\", @"\\");
ManagementObject lfs = new
ManagementObject(@"Win32_LogicalFileSecuritySetting.Path='" + lsString
+ "'");

ManagementBaseObject outP = lfs.InvokeMethod("GetSecurityDescriptor",
null, null);
if (((uint)(outP.Properties["ReturnValue"].Value)) == 0)
{
ManagementBaseObject Descriptor =
((ManagementBaseObject)(outP.Properties["Descriptor"].Value));
ManagementBaseObject[] DaclObject =
((ManagementBaseObject[])(Descriptor.Properties["Dacl"].Value));
DumpACEs(DaclObject);
}
liFolderCounter++;

DirectoryInfo d = new DirectoryInfo(lsCurrentFolderPath);
DirectoryInfo[] dis = d.GetDirectories();
foreach(DirectoryInfo di in dis)
{
try
{
lsCurrentFolderPath = di.FullName.ToString();

this.lblStatusLabel.Text = "Enumerating folder: ";
this.lblStatusLabel.Refresh();
this.lblStatus.Text = lsCurrentFolderPath;
this.lblStatus.Refresh();
Get_Folders_Simple();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error parsing folder " +
lsCurrentFolderPath);
this.Close();
}
}
}

I see two major problems with your code:
1. you are updating the UI from a NON UI Thread, this is not allowed in
Windows, you should marshal the call using Control.Invoke or BeginInvoke.
2. What if an exception is being thrown in the firts part of the thread
procedure? The procedure will return and the Timer will be stopped probably
before it gets fired the first time.
I suggest you start debugging ;-)

Willy.
 
J

Jason

Can you supply any examples of marshalling? Is this the same as
delegates? I tried using delegates to update the UI from the child
thread from examples off of MSDN, but couldn't ever get it to work.
 
Top