I have a XAML form that I would like two independent features threaded out of the main XAML execution thread: 1.) a timer control that ticks up, and 2.) implement a pause button so I can freeze a set of procedural set of activities and clicking on the pause button again will resume.
When I start the form, the entire app freezes. Because of this I can’t interact with btnPause control. I got the timer class to work, but it (lblTimer) updates in chunks, or whenver it looks like the CPU isn’t busy on the main thread.
I tried to create a class “Task” that wraps a class or method in its own thread so I can control.
Automation.Task AutomationThread = new Automation.Task();
Automation.Task TimerThread = new Automation.Task();
Later on, I attempted to create a stopwatch class and assign the TimerThread to it so I can manage it independently.
Automation.WatchTimer stopwatch = new Automation.WatchTimer(lblTimer, TimerThread);
class Task
{
private ManualResetEvent _shutdownFlag = new ManualResetEvent(false);
private ManualResetEvent _pauseFlag = new ManualResetEvent(true);
Thread _thread;
public Task() { }
public void Start()
{
_thread = new Thread(DoWork);
_thread.Start();
}
public void Resume()
{
_pauseFlag.Set();
}
public void Stop()
{
_shutdownFlag.Set();
_pauseFlag.Set();
_thread.Join();
}
public void DoWork()
{
do
{
_pauseFlag.WaitOne(Timeout.Infinite);
}
while (!_shutdownFlag.WaitOne(0));
}
// I AM NOT SURE IF THIS IS THE RIGHT APPROACH
public void DoWork(Func<void> method????)
{
do
{
// NOT SURE WHAT TO PUT HERE
// This is where I want it to do a method
// that wraps a long chain of procedural items
// where I can pause (block) and unpause through the UI
}
while (!_shutdownFlag.WaitOne(0));
}
class WatchTimer
{
public WatchTimer(System.Windows.Controls.Label lbl, Automation.Task worker)
{
lblField = lbl;
worker.Start();
}
private System.Windows.Controls.Label lblField;
Timer time = new Timer();
Stopwatch sw = new Stopwatch();
public void Start()
{
time.Start();
sw.Start();
time.Tick += new EventHandler(time_Tick);
}
public void Stop()
{
time.Stop();
sw.Stop();
}
public void Reset()
{
sw.Reset();
lblField.Content = this.elapsedTime();
}
public string elapsedTime()
{
TimeSpan ts = sw.Elapsed;
// return formatted TimeSpan value
return String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
}
private void time_Tick(object sender, EventArgs e)
{
lblField.Content = this.elapsedTime();
}
}
The timer appears to work, but it still spits updates in chunks – does this mean it’s not on its own thread?
The apparent hang is caused because one CPU is pegged at 100%. This is because the initial state of the
_pauseFlagis set to signaled. So when the main thread callsnew Thread(DoWork), theDoWorkis constantly blowing past the_pauseFlag.WaitOneand running in a tightdo/whileloop.To wrap some method in a thread, with pausing, this could be doable. You would have to remove the
do/whilefrom theDoWorkmethod. So your sequential code inDoWorkwould have to frequently check the paused event signaled state, in between the subtasks, inner loops, or whatever you would have in the sequential work method.