R
RedLars
The below method is executed in a separate thread, processing tasks
added to a queue.
private void Thread_Main() {
while (!TerminatedThread) {
// Next() blocks if queue is empty
IJob job = queue.Next() as IJob;
if (job != null) job.Execute();
}
}
To add tasks there are two public methods;
public void AddJob(IJob job) {
queue.Add(job);
}
public void AddJob(IJob job, int intervalTime) {
Timer timer = new Timer(new TimerCallback(InternalAddJob), job,
intervalTime, intervalTime);
timerList.Add(timer);
}
private void InternalAddJob(object obj) {
IJob job = obj as IJob;
if (job != null) AddJob(job);
}
And to start the execution in the thread:
public void Start() {
thread = new Thread(new ThreadStart(this.Thread_Main));
thread.Start();
}
This setup has worked fine so far. Now I need to implement a stop()
method which brings up a few concerns regarding thread safety.
A few comments
* A job.Execute() beeing executed must be completed before the thread
is stopped.
* A job.Execute() operation might take upto a few seconds to complete
(Asynch operation).
* Any unprocessed tasks in the queue, or created timers shall not be
deleted by Stop() method.
* The Queue (queue variable) has a Wakeup() method that stops the
queue.Next() from blocking and returns null;
To prevent stop() occuring during execution of a job a lock(..) was
introduced.
private object threadLocker = new object();
private void Thread_Main() {
while (!TerminatedThread) {
lock (threadLocker) {
IJob job = queue.Next() as IJob;
if (job != null) job.Execute();
}
}
}
To actually stop the while loop from running I thought about adding
Monitor.Wait(...) to the loop. But to be able to add such mechanism I
would need a state flag to distinguish between running and not running
(stopped) mode. So I thought about adding private enum State
{ Created, Started, Stopped };
private volatile State state;
private ManualResetEvent StopThreadResetEvent = new ManualResetEvent
(false);
private void Thread_Main()
{
while (!TerminatedThread) {
if (state == State.Started) {
lock (threadLocker) {
IJob job = queue.Next() as IJob;
if (job != null) job.Execute();
}
}
else if (state == State.Stopped)
{
Monitor.Wait(StopThreadResetEvent);
}
}
So would it be enough to implement the stop method like this (?);
private void Stop() {
if (state == State.Started) {
state = State.Stopped;
queue.Wakeup();
}
}
From what I can understand this would not guarantee that Thread_Main
is at Monitor.Wait(...) when Stop() returns.
Could that be a problem? I guess I could add
lock (threadLocker) { /* no code */ }
after Wakeup() as a form of waiting until Thread_Main has completed
its current task.
I would also need to change the Start() method a bit;
public void Start() {
if (state == State.Created)
thread = new Thread(new ThreadStart(this.Thread_Main));
thread.Start();
}
else if (state == State.Stopped)
{
state = State.Started
StopThreadResetEvent.Set();
}
}
What if Stop() and Start() are executed within a very short timeframe
- could that cause a problem with the current code?
I get the feeling I'm missing something when it comes handling state
\state-changes in a multi-threaded environment.
Appreicate any comments.
added to a queue.
private void Thread_Main() {
while (!TerminatedThread) {
// Next() blocks if queue is empty
IJob job = queue.Next() as IJob;
if (job != null) job.Execute();
}
}
To add tasks there are two public methods;
public void AddJob(IJob job) {
queue.Add(job);
}
public void AddJob(IJob job, int intervalTime) {
Timer timer = new Timer(new TimerCallback(InternalAddJob), job,
intervalTime, intervalTime);
timerList.Add(timer);
}
private void InternalAddJob(object obj) {
IJob job = obj as IJob;
if (job != null) AddJob(job);
}
And to start the execution in the thread:
public void Start() {
thread = new Thread(new ThreadStart(this.Thread_Main));
thread.Start();
}
This setup has worked fine so far. Now I need to implement a stop()
method which brings up a few concerns regarding thread safety.
A few comments
* A job.Execute() beeing executed must be completed before the thread
is stopped.
* A job.Execute() operation might take upto a few seconds to complete
(Asynch operation).
* Any unprocessed tasks in the queue, or created timers shall not be
deleted by Stop() method.
* The Queue (queue variable) has a Wakeup() method that stops the
queue.Next() from blocking and returns null;
To prevent stop() occuring during execution of a job a lock(..) was
introduced.
private object threadLocker = new object();
private void Thread_Main() {
while (!TerminatedThread) {
lock (threadLocker) {
IJob job = queue.Next() as IJob;
if (job != null) job.Execute();
}
}
}
To actually stop the while loop from running I thought about adding
Monitor.Wait(...) to the loop. But to be able to add such mechanism I
would need a state flag to distinguish between running and not running
(stopped) mode. So I thought about adding private enum State
{ Created, Started, Stopped };
private volatile State state;
private ManualResetEvent StopThreadResetEvent = new ManualResetEvent
(false);
private void Thread_Main()
{
while (!TerminatedThread) {
if (state == State.Started) {
lock (threadLocker) {
IJob job = queue.Next() as IJob;
if (job != null) job.Execute();
}
}
else if (state == State.Stopped)
{
Monitor.Wait(StopThreadResetEvent);
}
}
So would it be enough to implement the stop method like this (?);
private void Stop() {
if (state == State.Started) {
state = State.Stopped;
queue.Wakeup();
}
}
From what I can understand this would not guarantee that Thread_Main
is at Monitor.Wait(...) when Stop() returns.
Could that be a problem? I guess I could add
lock (threadLocker) { /* no code */ }
after Wakeup() as a form of waiting until Thread_Main has completed
its current task.
I would also need to change the Start() method a bit;
public void Start() {
if (state == State.Created)
thread = new Thread(new ThreadStart(this.Thread_Main));
thread.Start();
}
else if (state == State.Stopped)
{
state = State.Started
StopThreadResetEvent.Set();
}
}
What if Stop() and Start() are executed within a very short timeframe
- could that cause a problem with the current code?
I get the feeling I'm missing something when it comes handling state
\state-changes in a multi-threaded environment.
Appreicate any comments.