I miss those old events in this brave new world!

G

Guest

This is just a comment.

I was very surprised to find out that there are no named events support in
..NET framework! Sure, mutex objects can do most of IPC work, but there are
some cases that mutexes do not fit in (because mutexes have a unique thread
ownership feature).

For example (this may be very hard to understand, just like all other
synchronizing problems):

1. A parent process spawns a child process to do a job.

2. The parent has to make sure that the child starts the job or the child
exits prematurely on errors. It also has to have a way to tell the child to
stop working.

3. So in this brave .NET world, I have only one choice - two mutexes for the
IPC. One is for 'quit' signal, the other is for 'error' signal (when errors
occur, the child process exits).

4. Now the parent has the following logic:
get_unique_signal_names(); // Guid is used
create_quit_signal(); // intially owned
create_error_signal(); // not initially owned;
create_child_process_config(); // create a config file for the child
process
create_child_process_with_config(); // spawn the child process with
created config file
wait_for_child_process_or_error_signal(); // wait any of them
if(process exited)
{
call_error_handler();
}
else
{
user_ineration(); // provide UI to let user stop child process
}

5. The child process does this logic:
get_signal_names_from_config(); // they are in app.exe.config
open_quit_signal();
open_error_signal();
try
{
intialization_for_job();
}
catch(error)
{
set_error_signal();
return -1;
}

start_job(); // e.g., starting a listening socket
wait_for_quit_signal(); // enter wait state;

6. Everything is fine, right? But there is only one *small* problem. This
problem is caused by the unique feature of mutex objects - thead ownership.
Simply put, the above logic does not gurantee
wait_for_child_process_or_error_signal() always indicate the correct
situation.

The error signal is created not owned. Since no thread has ownership of
this mutex, its state is always *signaled*; unlike event objects, they are
either signaled or nonsignaled. So it is not 100% safe that when the code
gets to wait_for_child_process_or_error_signal(), the child process has
already does open_error_signal()!

It took me hours to find out this *small* problem. I think it's a small
problem because programs now runs on fast computers, the chance is very rare
for the child process get choked before open_error_signal() and while the
parent process gets to wait_for_child_process_or_error_signal().

7. There is a solution. But it is clumsy (anyone who gets to this point
please point out a good way if he/she know one):

For the parent process:
for(;;)
{
Thread.Sleep(500); // don't exhaust CPU time
// wait for the child process to get ownership of this signal
if(done_signal.WaitOne(500, true)) // in case the child already has it
{
done_signal.ReleaseMutex(); // well, have to do get/release in pairs
}
else break;
}

For the child process:
open_error_signal();
get_ownership_of_error_signal(); // get ownership - a simple wait

8. That's why I miss those named events in the ugly old world. With named
events, I don't have to add the logic in note 7.

At last, I finished it. I thank for any explanation on why named events
extinct in the new world (except the performance issue).
 
G

Guest

Forget it. I think I have to use PInvoke to get the job done. Mutex cannot
handle this scenario (the logic in note 7 does not work either).
 
R

Richard Blewett [DevelopMentor]

I wrote a couple of threading utilities a while back including a thread that has a WaitHandle and a named event. Feel free to use

http://staff.develop.com/Richardb/dotnet/DM.Threading.zip

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk

nntp://news.microsoft.com/microsoft.public.dotnet.framework/<[email protected]>

This is just a comment.

I was very surprised to find out that there are no named events support in
.NET framework! Sure, mutex objects can do most of IPC work, but there are
some cases that mutexes do not fit in (because mutexes have a unique thread
ownership feature).

For example (this may be very hard to understand, just like all other
synchronizing problems):

1. A parent process spawns a child process to do a job.

2. The parent has to make sure that the child starts the job or the child
exits prematurely on errors. It also has to have a way to tell the child to
stop working.

3. So in this brave .NET world, I have only one choice - two mutexes for the
IPC. One is for 'quit' signal, the other is for 'error' signal (when errors
occur, the child process exits).

4. Now the parent has the following logic:
get_unique_signal_names(); // Guid is used
create_quit_signal(); // intially owned
create_error_signal(); // not initially owned;
create_child_process_config(); // create a config file for the child
process
create_child_process_with_config(); // spawn the child process with
created config file
wait_for_child_process_or_error_signal(); // wait any of them
if(process exited)
{
call_error_handler();
}
else
{
user_ineration(); // provide UI to let user stop child process
}

5. The child process does this logic:
get_signal_names_from_config(); // they are in app.exe.config
open_quit_signal();
open_error_signal();
try
{
intialization_for_job();
}
catch(error)
{
set_error_signal();
return -1;
}

start_job(); // e.g., starting a listening socket
wait_for_quit_signal(); // enter wait state;

6. Everything is fine, right? But there is only one *small* problem. This
problem is caused by the unique feature of mutex objects - thead ownership.
Simply put, the above logic does not gurantee
wait_for_child_process_or_error_signal() always indicate the correct
situation.

The error signal is created not owned. Since no thread has ownership of
this mutex, its state is always *signaled*; unlike event objects, they are
either signaled or nonsignaled. So it is not 100% safe that when the code
gets to wait_for_child_process_or_error_signal(), the child process has
already does open_error_signal()!

It took me hours to find out this *small* problem. I think it's a small
problem because programs now runs on fast computers, the chance is very rare
for the child process get choked before open_error_signal() and while the
parent process gets to wait_for_child_process_or_error_signal().

7. There is a solution. But it is clumsy (anyone who gets to this point
please point out a good way if he/she know one):

For the parent process:
for(;;)
{
Thread.Sleep(500); // don't exhaust CPU time
// wait for the child process to get ownership of this signal
if(done_signal.WaitOne(500, true)) // in case the child already has it
{
done_signal.ReleaseMutex(); // well, have to do get/release in pairs
}
else break;
}

For the child process:
open_error_signal();
get_ownership_of_error_signal(); // get ownership - a simple wait

8. That's why I miss those named events in the ugly old world. With named
events, I don't have to add the logic in note 7.

At last, I finished it. I thank for any explanation on why named events
extinct in the new world (except the performance issue).
 
G

Guest

Thanks. Though I have already done it using PInvoke, but I think your classes
are well designed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top