|
George_George wrote: "except that the caller doesn't get blocked if the worker's already busy with a task", any ideas?
Yes this is true. Caller won't be blocked. The example uses a queue system. When you enqueue new task, it will be added to the queue and immediately control will be given back. The program then processes each task depending on the availability of worker threads.
|
|
|
|
|
Thanks N a v a n e e t h,
1.
N a v a n e e t h wrote: Yes this is true. Caller won't be blocked. The example uses a queue system. When you enqueue new task, it will be added to the queue and immediately control will be given back. The program then processes each task depending on the availability of worker threads.
I agree. But the Enqueue operation will be blocked since it is using a lock object to do synchronization, right? Means if worker thread is at the same time Dequeue, the person who Enqueues must wait.
2.
I have an alternative implementation, which will use the following logics,
2.1 Sleep 1 second;
2.2 Check is a bool variable called stop is set by some other threads?
2.3 If stop is set, then stop current thread;
2.4 If stop is not set, then do some regular work, then go back to 2.1.
Does using event (as showed in the document you referred) has better performance compared with my alternative method?
regards,
George
|
|
|
|
|
George_George wrote: But the Enqueue operation will be blocked since it is using a lock object to do synchronization, right? Means if worker thread is at the same time Dequeue, the person who Enqueues must wait.
No. It won't block. You know, acquiring a lock is pretty fast. If you look at that code carefully, you will find lock is used only to dequeue items, and it will be released immediately once dequeued. Program won't hold the lock until it finishes executing the job. So it executes in a nonblocking fashion.
George_George wrote: Does using event (as showed in the document you referred) has better performance compared with my alternative method?
The example which I showed utilizes CPU well. It won't create much threads for processing each task. It will use the existing threads to spin between the tasks. A free thread will be allocated to process the next task.
Will the steps you provided satisfy your requirement ? As I understood from the previous messages, you are trying to execute a task before the previous task completes. I mean you need to execute it in each 1 second without blocking. If it is the case, looks like the steps you provided won't satisfy the requirement.
According to your code, when a task is processed, it is not checking the stop flag. So it won't exit until the currently processing task ends. Right ? Also it will block the thread until it finishes the operation, so you can't guarantee that it will be executed in each 1 second. Correct me if I got you wrong.
|
|
|
|
|
Thanks for your great reply, N a v a n e e t h!
Three more comments after some thinking.
1.
N a v a n e e t h wrote: only to dequeue items
No. When Enqueue, the lock is still used.
Here is the code. Any comments?
public void EnqueueTask (string task) {
lock (locker) tasks.Enqueue (task);
wh.Set();
}
2.
N a v a n e e t h wrote: It won't create much threads for processing each task. It will use the existing threads to spin between the tasks.
Which solution do you compare to when you mention "create much threads"? In my case, I only create one thread in the very first post.
If I use timer, then each time, the timer will create a new worker thread or reuse previous one?
3.
N a v a n e e t h wrote: Will the steps you provided satisfy your requirement ? As I understood from the previous messages, you are trying to execute a task before the previous task completes. I mean you need to execute it in each 1 second without blocking. If it is the case, looks like the steps you provided won't satisfy the requirement.
Sorry my English is not very good.
My requirement is to complete the current task before execute next task, and between each task execution iteration, sleep 1 second so that system could have more chances to do other things. Could you help to review my previous solution again to see whether it could achive requirement please?
regards,
George
|
|
|
|
|
George_George wrote: No. When Enqueue, the lock is still used.
Yes. Enqueue is fast and it won't block thread for anytime.
George_George wrote: If I use timer, then each time, the timer will create a new worker thread or reuse previous one?
Timer uses thread pool thread. Obviously it will be reused.
George_George wrote: My requirement is to complete the current task before execute next task, and between each task execution iteration, sleep 1 second so that system could have more chances to do other things
Either you can do parallel execution or sequential execution. If you need to execute the next only after the completion of first task, then you don't need such a producer/consumer solution.
|
|
|
|
|
Thanks N a v a n e e t h,
1.
Compared my original solution with using Timer, I think the advantage is I am using a single thread to execute (while Timer will use thread pool, not sure whether it is always the same thread), but disadvantege is I need to call sleep in order to execute next task.
So, I am confused, whether the performance of using Timer or using Sleep is better (I mean less performance overhead to the whole application)?
2.
N a v a n e e t h wrote: Either you can do parallel execution or sequential execution. If you need to execute the next only after the completion of first task, then you don't need such a producer/consumer solution.
Sorry, I have not made myself understood. What I am doing is the same as the producer/consumer scenario. The thread I described in my original very first post is the consumer thread, another thread is controller for push task for consumer and set stop status.
regards,
George
|
|
|
|
|
George_George wrote: Compared my original solution with using Timer, I think the advantage is I am using a single thread to execute (while Timer will use thread pool, not sure whether it is always the same thread), but disadvantege is I need to call sleep in order to execute next task.
Both will be same in this case. Timer uses a thread pool thread which is ready to go. So you can avoid the overhead of creating your own threads. You know, creating a thread is bit performance costly.
|
|
|
|
|
Thanks N a v a n e e t h,
I agree. Then what do you think are the pros and cons of using Timer compared with using Sleep, functional and performance?
regards,
George
|
|
|
|
|
I don't know exactly. Since timer uses a thread pool thread, I guess sleeping for a long time is bad as thread pool is shared.
|
|
|
|
|
Thanks N a v a n e e t h,
"sleeping for a long time is bad as thread pool is shared" -- I am confused. Do you mean if we use thread pool thread, and we "hold" the thread too long (e.g. using Sleep), then it will reduce the chance for other parties to use/share the same thread from the thread pool?
regards,
George
|
|
|
|
|
|
Compared of using Timer, maybe this solution is of better performance (means less performance impact to the whole system)? Any comments?
while (false == StopEvent.WaitOne(1000))
{
}
regards,
George
|
|
|
|
|
That's how I write Services. I use a Timer. If the process needs the ability to stop part way through then I also use a semaphore. In some cases, the Service runs a method in another class (with another semaphore) and that class has an event that the Service can raise to stop that method.
|
|
|
|
|
Thanks PIEBALDconsult,
"If the process needs the ability to stop part way through then I also use a semaphore. In some cases, the Service runs a method in another class (with another semaphore) and that class has an event that the Service can raise to stop that method." -- I am confused whether you are using event or semaphore or both? Could you show me your pseudo code please? Code clarifies much more.
regards,
George
|
|
|
|
|
Both; the second class' event handler sets its semaphore.
George_George wrote: Could you show me your pseudo code
I could, and I'll try to, but it's late now.
|
|
|
|
|
Thanks PIEBALDconsult,
Here is my code, please let me know if you think my code is the same as your ideas or not. I am using Event and Timer, but not semaphore. I want to learn from you about the new method.
class Program
{
static AutoResetEvent CheckEvent = new AutoResetEvent(false);
static bool stop = false;
static void ThreadMethod2()
{
while (true)
{
CheckEvent.WaitOne();
Console.WriteLine(DateTime.Now);
if (stop)
{
break;
}
else
{
}
}
}
static void OnTimedEvent(object source, ElapsedEventArgs e)
{
CheckEvent.Set();
}
static void Main(string[] args)
{
System.Timers.Timer aTimer = new System.Timers.Timer();
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Interval = 5000;
aTimer.Enabled = true;
Thread worker = new Thread(new ThreadStart(ThreadMethod2));
worker.Start();
Console.WriteLine("Press \'q\' to quit the sample.");
while (Console.Read() != 'q') ;
stop = true;
worker.Join();
return;
}
}
regards,
George
|
|
|
|
|
I'll use that as a basis for writing something for you tomorrow.
But you shouldn't need a Timer and a Thread and the while loop.
|
|
|
|
|
That will be great, PIEBALDconsult!
I am looking forward to learning from you.
regards,
George
|
|
|
|
|
Here's a simple console program that will display the time every five seconds until you press RETURN.
namespace Template
{
public partial class Template
{
private System.Timers.Timer tt = null ;
public Template
(
int Interval
)
{
tt = new System.Timers.Timer ( Interval ) ;
tt.Elapsed += F ;
return ;
}
private void
F
(
object sender
,
System.Timers.ElapsedEventArgs e
)
{
System.Console.WriteLine ( System.DateTime.Now.ToString() ) ;
return ;
}
public void
Start
(
)
{
tt.Start() ;
return ;
}
public void
Stop
(
)
{
tt.Stop() ;
return ;
}
[System.STAThreadAttribute()]
public static int
Main
(
string[] args
)
{
int result = 0 ;
try
{
Template x = new Template ( 5000 ) ;
x.Start() ;
System.Console.ReadLine() ;
x.Stop() ;
}
catch ( System.Exception err )
{
while ( err != null )
{
System.Console.WriteLine ( err.Message ) ;
err = err.InnerException ;
}
}
return ( result ) ;
}
}
}
|
|
|
|
|
Thanks PIEBALDconsult,
I have got your idea. Compared with my original code using sleep in the very first post, does your code have better performance (e.g. less impact to the whole application performance)?
regards,
George
|
|
|
|
|
George_George wrote: better performance
Doubt it's any better or worse, but I find it easier to read and maintain. Which is why I use Timers for my Services.
|
|
|
|
|
Thanks PIEBALDconsult,
1.
We have discussed solutions using only Timer, using only Sleep. Is it possible to have solutions using only Event? (I showed a solution using Timer together with Event, which I think is not good.)
2.
The most concern why I can not find a solution using Event only is, there is no way to check whether a signal is set or not after Wait (with timeout), right?
regards,
George
|
|
|
|
|
1) Not to my knowledge.
2) Those events (which I don't use and hadn't heard of until you mentioned them) require a thread of some sort.
Unless this is homework and you have to use those events, just do what you know works.
|
|
|
|
|
Thanks PIEBALDconsult,
This is not homework. Just my interest to find alternative solutions.
Here is my question showed by the code, it seems there is no way to check whether the signal is set or not after WaitOne(1000) returns, right? So, we can not just use a singal to check the stop condition for a thread, and we need some other approaches to check?
(my previous ideas is to check whether the signal is set or not, if it is set after WaitOne(1000), then I can stop the thread, but after MSDN document study, seems no way to check whether a signal is set or not after WaitOne(1000)?)
static void ThreadMethod3()
{
while (true)
{
CheckEvent.WaitOne (1000);
Console.WriteLine(DateTime.Now);
}
}
regards,
George
|
|
|
|
|
I don't know, I don't use those, I don't foresee a need for them.
|
|
|
|