Solved

Threads starting/stopping other threads, suspending itself?

Posted on 2004-08-17
20
616 Views
Last Modified: 2012-05-05
I'm curious if these worker threads call the static class on the form (first off do I need to lock the static class variables?)
If which lines are bad (and why preferably) (i'm going to write really short code without { } just to get the point across}

Class WorkThread
{
  Thread wThread

  WorkThread()
    wThread = new Thread(new ThreadStart(main));

  main()
    Do some Work
    form1.MainThread.resume();  
    // Do i need to do any locking on the MainThread?  If not why not?
}

Class MainThread
{
  Thread mThread

  MainThread()
    wThread = new Thread(new ThreadStart(main));

  main()
  {
    Create 5 threads
    Each Thread is put into a serialized Hashtable
    try
      While (Hashtable.count > 0)
      {
        Thread.CurrentThread.Suspend();  // Is this really ok?
        loop through threads, remove dead thread from hashtable
      }
    finally  //I'll programmatically get out of the while loop (while loop will have more)
      loop through threads, abort "alive" threads      
  }
 
  resume()
    if ((mThread.ThreadState & ThreadState.Suspended) == ThreadState.Suspended)
      mThread.Resume()
   
Class form1 : System.Windows.Forms.Form //forms really irrelevant
   
  public static MainThread threadManager;

  form1()
    threadManager = new MainThread();


I'm basically thinking of a way for the threads to tell the master thread that they are done.  
I know I could do this with MRE.  I'm just curious about why what I've done above wouldn't work.
The three questions:
1a. Do I need to lock public static MainThread?
1b. If so is it just because its another variable, or because its calling a function to another thread.
2. Is it really ok to call Thread.CurrentThread.Suspend() ?
0
Comment
Question by:ErikPhilips
20 Comments
 
LVL 3

Assisted Solution

by:bigjim2000
bigjim2000 earned 150 total points
Comment Utility
I think the best way to do it is to have your WorkerThread class have a constructor like this:
public WorkThread(ref MainThread parentThread){}

Then each of your worker threads has access to the main thread.

Also, whenever you are accessing either global or static variables with multiple threads, it is always better to lock them when you use them.  Even with static variables you can get into trouble.

The answer to your question 1b is because you are referring to a variable that is outside the main scope of the thread.... you can still see it, but so can everything else ;-)

It's fine to call the CurrentThread.Suspend() method.  

As for cleaning things up, I'd personally have a method in the MainThread class that looks like this:
public void Remove(WorkerThread wt){}

This way, your worker threads can just call this thread when they are done... if they have the reference to the parent that is.


I hope I have been of some help to you!

-Eric
0
 
LVL 48

Assisted Solution

by:AlexFM
AlexFM earned 100 total points
Comment Utility
>> I'm basically thinking of a way for the threads to tell the master thread that they are done.  

http://www.codeguru.com/Csharp/Csharp/cs_syntax/article.php/c5851/
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
"I know I could do this with MRE.  I'm just curious about why what I've done above wouldn't work."

>>http://www.codeguru.com/Csharp/Csharp/cs_syntax/article.php/c5851/
>> "ManualResetEvent m_EventStopThread;"
>> "ManualResetEvent m_EventThreadStopped;"
0
 
LVL 14

Expert Comment

by:AvonWyss
Comment Utility
Have a look a Thread.Join() - you can use this method on any thread to wait for it to be terminated. You can also use Join() on a thread which is already done. Therefore, you can wait for all your running threads using Join() in a sequential matter and the waiting loop will be done as soon as all threads have done their work and terminated.
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
True.  If master thread owns threads A B C D, and one of them is going to finish randomly first, which thread would the main thread join on?
0
 
LVL 14

Expert Comment

by:AvonWyss
Comment Utility
All in any order. If the thread was already done, Join() will return immediately. Therefore, you just have to make sure to run Join() on all the owned threads once, and this will do what you want.
0
 
LVL 14

Expert Comment

by:AvonWyss
Comment Utility
(I'm assuming that you want to know when all threads have finished. If this is not what you want, I misunderstood the question...)
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
Yes, but is Join going to block the current (mainThread) from executing?  If so then I can't join on any other thread until the first Joined thread is finished (which means if another thread finishes, I am sort of wasting cycles).  I understand that this would allow me to a basically to wait for X (4 in this case) threads to finish, but thats not exactly what I'm looking for (or am I wrong?).

0
 
LVL 14

Expert Comment

by:AvonWyss
Comment Utility
Well, if you want to have a thread wait until all of its child threads have finished, Jion() is about the most efficient methd you can use. But you have to tell us if that's actually what you are looking for or if you rather want to wait for the first thread to finish, or what exactly. This you must tell us...
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
Ok what I'm going to code is a thread managerThread with X child threads.  After all threads start, the main thread should be "paused" until woken up by any child thread.  Now using ManualResetEvent (mre), i could block the main Thread.  Is this actually preventing the main thread from doing work like a suspend() would?  I don't believe it is, because I believe that anytime it has a chance it checks the MRE to see if it should continue, it is taking up processing time.  The point is that I don't want the main thread doing anything if it doesn't have to.  Secondly, the child threads are going to do blocking work (ie a task waiting for an incoming connection).  When the child thread is finished with its work it needs to tell the managerThread to wake up to do something.

With that scenario, I could use MRE.  I understand MRE, but I don't see why I should use it if I can have child threads suspend, resume the threadManager?  bigjim2000 says its ok to call CurrentThread.Suspend(), and I believe him.  Using his code when the child thread is created, it could have a "pointer"(mt) to the the managerThread.  Technically I could mt.resume().  Would I need to lock it?  Is it ok to resume a thread in that manner?
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 14

Accepted Solution

by:
AvonWyss earned 250 total points
Comment Utility
Ok, so if I understand right, you want the "management thread" to wait for an event from an "child" thread? In this case, I'd also use a MRE, but you have to be careful so that your code can handle situations where the MRE is set by more than one child thread concurrently. Another variant is to have each of your child threads carry a MRE (or maybe better an ARE), and to do a WaitHandle.WaitAny() on these wait handles. This will maybe do what you want...
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
I'm going to use MRE apparently.  I wasn't really looking for how to use MRE. I was looking for a reason not to have threads suspend/resume other threads.
0
 
LVL 14

Expert Comment

by:AvonWyss
Comment Utility
Well, the answer could be that a MRE is implicitly blocking the calling thread (and doing this^just as cheap as a suspende thread is), and you don't have to worry that much about race situations (for instance, where child a wants to signal the master thread and unsuspends it, but if the master thread was already handling thread b's request and was just going to suspend itself, the thread a will not be handled... ans such stuff).
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
Thats just it, its not an event that needs to be handled.  If thread A starts threadManager, and then thread B wants to start the threadManager, but the threadManager is already awake, thread B just doesn't care.  I know it may sound weird.  It's kinda like people who walk up to an intersection to cross the street.  Pedestrian A hits the "walk across the street" button, but when Pedestrian B hits it, the code doesn't care because pedestrian A already hit it.  When the signal is about to change, it will block threads from walking on the red light (stops all threads), then it starts the threads in the right direction, and wait for someone to hit the button to walk the otherway.  That make sense?
0
 
LVL 14

Expert Comment

by:AvonWyss
Comment Utility
Well, I didn't mean to write that this must be a problem. But one has to be very careful when designing such thread synchronisation szenarios due to the possible issues with concurrency, especially race conditions and deadlocks.

What I wanted to say is this: assume that the threadmanager has just finished handling thread A and is going to sleep. Now, during the very call to CurrentThread.Suspend(), it may happen (and it will certainly happen every now and then) that thread B wants to wake the threadmanager. Since the manager is already running, nothing happens. But when the threadmanager is continuing execution, it will still go to sleep, therefore not handling thread B's request. That's a race condition. And this stuff is what makes such code difficult to write.

Do you see what I mean?
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
Ahh indeed!  I completely see.  And I could see how that would make many things not work.

I'm not going to assume I won't get in trouble with my code, but I'll explain in more detail whats happening.  This will probably sound weird but its the best desription of what I'm trying to do, and what I'm trying to accomplish with threads.  You are already aware of the manager and worker threads, no big deal. Manager creates 5 threads, goes to sleep.  Each thread then waits for in incoming connection (say an http request for a page).  The worker threads takes the connection, does works, sends a response, drops the connection, adds (via Lock) information to the manager thread "incoming todo", wakes the manager, and finally waits for a connection(blocking).  The thread Manager then Locks, clones, clears, unlocks the "incoming todo", works on the cloneset, once finishes updates a database, and goes back to sleep.  Since the manager doesn't really care about the workers, and the workers don't really care about the manager, I was just looking for alternative code so I would have to add more variables and checks everywhere for such a simple idea.

Create a MRE variable, MRE set , MRE watch, do work(thread reset), MRE set it.

Or just simply suspend,  thread.ownerthread.resume()

one + x threads suspend/resume statements (x+1) -- OR --  1 variable + (2 + x * statements to lock set) statements.

I don't know call me crazy, one seems much easier when I'm trying not to accomplish a full "EVENT" type system between threads.
0
 
LVL 14

Expert Comment

by:AvonWyss
Comment Utility
Have you already thought about not using threads at all, but rather do calls on async delegates? These are handled by the built-in ThreadPool class and they work well in most situations like this. The benefit of the async delegates is that you can have a callback method called when the work is done and you don't have to bother about thread management at all; also, thread pools are "cheaper" since they are recycled (e.g. not destroyed and recreated for each task). Another benefit of async delegates is that you can pass type-safe parameters to the called method and you can even pass on some state object which will be passed on to the callback method.

YourDelegate delegate=new YourDelegate(YourMethod);
delegate.BeginInvoke(yourArgs, new AyncCallback(YourCallbackMethod), yourCallbackState);

In the callback, make sure to call delegate.EndInvoke() - note that you can find the delegate where the Begin method was called on by casting the IAsyncResult to AsyncResult - see help for more information.


What is the job the manager is supposed to do? Because maybe you could also do this job in the callback (of course making sure that you work on synchronized objects), and not bother about the notification stuff at all. Or, you could create a synchronized queue class which also hosts a MRE which is set when the list is not empty and reset when it is empty. By using this queue, you could have your manager thread wait on the queue's MRE and this would make things very elegant and failproof. Something like this (may be buggy, but I guess you'll get the idea):

public WaitableQueue: Queue {
    private ManualResetEvent notEmpty;

    //... implement the constructor etc. here

    public override Enqueue(object obj) {
        lock (SyncRoot) {
            base.Enqueue(obj);
            notEmpty.Set();
        }
    }

    public override object Dequeue() {
        for (;;) {
            notEmpty.WaitOne(); // this must not be in the lock() section because it would prevent insertion of items by other threads. That's why I had to make this strange "inifinite" loop.
            lock (SyncRoot) {
                if (Count>0) {
                    return base.Dequeue();
                } else {
                    notEmpty.Reset(); // nothing left to do, reset event an loop
                }
            }
        }
    }
}

Now, in the manager, just call Dequeue() - it will block until a new item has been added. In the client threads, just do a Enqueue() and forget about any notifications. That's it. ;-)
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
I don't know if that will work or not, because I have not used Async Delegates before.  My threads are calling a Wrapped COM object that blocks the thread.  Would a allow multiple connections at the same time?  Thats why I'm using threads, to allow multiple connections via Named Pipes IPC.
0
 
LVL 14

Expert Comment

by:AvonWyss
Comment Utility
Yes, Async delegates allow multiple functions to be executed in parallel. But it scales better then normal threading, since threads are not created and destroyed all the time, and the pool will have an upper limit of concurrent calls it does handle simultaneously (this is dependent on the machine where your app is running; for instance, mutliple-CPU systems will get more threads then single CPU ones). This prevents the system from stalling due to thread context switches overhead.
0
 
LVL 4

Author Comment

by:ErikPhilips
Comment Utility
That is great information to know.  You guys have been very helpful, especially you AvonWyss.   Thanks!
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now