Help - Multithreading Question

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I am trying to execute a blocking call in a thread which times out after a
certain time.
The problem I am having is that the thread does not seem to die after it is
done doing its work. I have a MAIN that never dies, the problem I am having
is that either on timeout or on successfull completion of the "blockingcall"
the process space in which my MAIN runs still shows the created thread IDs as
active with a couple of references and handles. I am using process explorer
from SysInternals to look at the ThreadIDs

Code is below and am using this snippet in a web app.

thanks


Here is my main:

for(int i=1; i<=1; i++)
{
TTEncap TTE = new TTEncap(("Thread" + i.ToString()));
Thread myThread = new Thread(new ThreadStart(TTE.blockingCall));
int dueTime = 10000 + (i * 5000);
Timer timer1 = new Timer(new TimerCallback(TTE.OnTimer), myThread, dueTime,
Timeout.Infinite);
TTE.ThreadTimer = timer1;
myThread.Start();
}

Console.WriteLine("Main runs on Thread: {0}\n",
AppDomain.GetCurrentThreadId());

// Main keeps working on something else forever (MAIN NEVER DIES)


HERE is the TTE Class:

public class TTEncap
{
public string TEName = null;
public Timer ThreadTimer;

public TTEncap(string tName)
{
TEName = tName;
}

public void blockingCall()
{
try
{

Console.WriteLine("BlockingCall runs on Thread: {0}\n",
AppDomain.GetCurrentThreadId());

while(true)
{
}

}
catch (Exception ex)
{
Console.WriteLine("Exception BC {0}: {1}\n",
AppDomain.GetCurrentThreadId(), ex.Message);
}
finally
{
this.ThreadTimer.Dispose();
}
}
public void OnTimer(object obj)
{
try
{
Console.WriteLine("TTEncap Name: {1} Timer runs on Thread:
{0}\n", AppDomain.GetCurrentThreadId(), TEName);

Thread tt = (Thread) obj;
tt.Abort();
}
catch (Exception ex)
{
Console.WriteLine("Exception OnTimer: {0}\n", ex.Message);
}
}
}
 
Hi,
I don't know if this will help but...
Instead of while(true) { } couldn't you do a while (not timeout) { } and set
the timeout boolean to true in your timer event handler? That way the loop
will end when the timer fires. Also, are you calling unmanaged code in your
while loop? I'm not sure but I think Abort doesn't Abort during calls to
unmanaged code.
 
Rob,

It is managed code. The problem I am having is not with the while loop.
Everything works well when the timer fires or when while loop executes
gracefully.

The problem is that after the "finally" block exectues, since I don't have
any control returning back to the MAIN thread (my MAIN is always running),
the thread ID is still shown as a valid handle (even after the "finally"
block executes).

In other other words the threads continue to exist in the process space of
my MAIN even after executing the complete thread.

thanks
 
Hi,
Did you try a call to Join on the thread after the call to Abort?
From help: The thread is not guaranteed to abort immediately, or at all.
This situation can occur if a thread does an unbounded amount of computation
in the finally blocks that are called as part of the abort procedure, thereby
indefinitely delaying the abort. To ensure a thread has aborted, invoke a
Join method on the thread after calling Abort.

Do you examine the ThreadState after the call to Abort either from its own
thread or the main thread just to see if its value makes sense?

Also, did you see this statement from Help: An operating-system ThreadId has
no fixed relationship to a managed thread, because an unmanaged host can
control the relationship between managed and unmanaged threads. Specifically,
a sophisticated host can use the CLR Hosting API to schedule many managed
threads against the same operating system thread, or to move a managed thread
between different operating system threads.

So, since you are viewing the threads with with process explorer is it
possible you are viewing the operating system thread but it is no longer
running your managed thread?

Sorry, but this is all I can come up with,
Rob
 
Rob,

Wouldn't a join block my main thread though? Also Iam aborting the thread
only if it times out.
In cases where the blocking call executes within the allocated time, the
Abort is NOT called (I was expecting the thread to terminate normally. ( I
did put in an Abort though, and it didn't work).
I did look at the threadstate (from within the thread) , it is alive.

This is an interesting point, my threads are running under aspnet_wp.exe and
if it is a using a ThreadPool there is a potential for re-use of the same
thread.

Is there any other way to clearly tell if my thread has exited, especially
since Iam not blocking in my Main ?

thanks for all your help Rob
 
Hi,
A Join would block until the thread that issues the Join. In your case
wouldn't that be a ThreadPool thread because the Join is issued from a Timer
callback? I think the timer callback is run from a ThreadPool thread. It
would be interesting to see if the call to Join ever returns (just to see if
the thread EVER terminates).

When the blockingcall completes normally (instead of Abort) does the thread
go away?

Did you check the IsThreadPoolThread property on the thread to see if it is
in fact part of the pool?

Use can use Task Manager to view the ThreadCount before you create those
threads, while they are running, and after they should have been terminated
to see if the counts give any useful info.

I don't know of any way to know for sure that your thread terminated. Could
you add some debug code in your main thread to periodically check the IsAlive
or ThreadState of the threads it created to see if they eventually terminate
or at least have the ThreadState change to AbortRequested?
 
True, but Iam handling both the cases

Case 1: When the timer goes off and Case 2, when the blocking call
terminates normally.
The timer.Dispose in the "finally" block should take care of the timer
thread from the from the ThreadPool.

Even when the blocking call terminate normally, the threadID still shows up
in the ProcessExplorer. I just noticed that the thread got created only after
my call.

thanks
 
Rob,

I put a join in the MAIN thread and then checked the state, it is "STOPPED".
But the Tread ID still remains in the process space.

thanks
 
I guess that is good that it is stopped. Unfortunately I don't know how to
confirm whether it is a problem or not that the threadID is still in the
process space since there isn't necessarily a one-to-one correspondence
between the .NET managed thread and Windows thread. You did say that this
thread ID isn't in the process space before you create your threads, right?

While debugging the process you could check to see if it is listed in the
Thread combo box (turn on View | Toolbars | Debug location) when you hit a
breakpoint. That might provide a clue that the thread is really hanging
around. Other than that
the only things I would know to examine are the process threadcount in Task
Manager.

Sorry I'm out of ideas,
Rob
 
Thanks for your support


Rob C said:
I guess that is good that it is stopped. Unfortunately I don't know how to
confirm whether it is a problem or not that the threadID is still in the
process space since there isn't necessarily a one-to-one correspondence
between the .NET managed thread and Windows thread. You did say that this
thread ID isn't in the process space before you create your threads, right?

While debugging the process you could check to see if it is listed in the
Thread combo box (turn on View | Toolbars | Debug location) when you hit a
breakpoint. That might provide a clue that the thread is really hanging
around. Other than that
the only things I would know to examine are the process threadcount in Task
Manager.

Sorry I'm out of ideas,
Rob
 
Back
Top