views:

120

answers:

2

I have some code that starts a couple of threads to let them execute, then uses a while loop to check for the current time passing a set timeout period, or for the correct number of results to have been processed (by checking an int on the class object) (with a Thread.Sleep() to wait between loops)

Once the while loop is set to exit, it calls Abort() on the threads and should return data to the function that calls the method.

When debugging and stepping through the code, I find there can be exceptions in the code running on the separate threads, and in some cases I handle these appropriately, and at other times I don't want to do anything specific.

What I have been seeing is that my code goes into the while loop and the thread sleeps, then nothing is returned from my function, either data or an exception. Code execution just stops completely.

Any ideas what could be happening?


Code sample:

System.Threading.Thread sendThread = 
     new System.Threading.Thread(new System.Threading.ThreadStart(Send));
sendThread.Start();

System.Threading.Thread receiveThread = 
     new System.Threading.Thread(new System.Threading.ThreadStart(Receive));
receiveThread.Start();

// timeout
Int32 maxSecondsToProcess = this.searchTotalCount * timeout;
DateTime timeoutTime = DateTime.Now.AddSeconds(maxSecondsToProcess);
Log("Submit() Timeout time: " + timeoutTime.ToString("yyyyMMdd HHmmss"));

// while we're still waiting to receive results & haven't hit the timeout, 
// keep the threads going
while (resultInfos.Count < this.searchTotalCount && DateTime.Now < timeoutTime)
{
    Log("Submit() Waiting...");
    System.Threading.Thread.Sleep(10 * 1000); // 1 minute
}

Log("Submit() Aborting threads");    // <== this log doesn't show up

sendThread.Abort();
receiveThread.Abort();

return new List<ResultInfo>(this.resultInfos.Values);
+3  A: 

Thread.Abort Raises a ThreadAbortException in the thread on which it is invoked

You shouldn't let exceptions escape from your threads ever - you should have exception handling in your threaded object. At the very least there should be a try\catch block around the code in the threaded object.

David Relihan
BeckyLou
+5  A: 

So, you really shouldn't use the Sleep method on the thread for synchronization purposes. This is what synchronization classes such as ManualResetEvent are for, as well as the Asynchronous Programming Model (IAsyncResult implementations).

A better approach here would be to create a delegate with the signature of the method you want to run asynchronously. Then, assign the method group that is the entry point for the asynchronous operation to an instance of that delegate and call BeginInvoke on the delegate instance.

From there, you would run your loop, expect you would call the overload of WaitOne on the WaitHandle returned by the AsyncWaitHandle property of the IAsyncResult implementation returned by the call to BeginInvoke on the delegate.

This will cause less reliance on the Sleep method (which is bad for synchronization in general).

If you have the option to use .NET 4.0, then you might want to take a look at the Task class in the System.Threading.Tasks namespace as it provides an even better way to handle asynchronous processing, cancellation, and wait timeouts.

casperOne
Thanks for this, I’ve used delegates for async programming before, but how could I still impose my timeout to stop processing after a set period of time across both delegates?
BeckyLou
@BeckyLou: Thread.Abort is definitely the *wrong* way to do it, as it's not a graceful exit. Like any async programming, you would have to synchronize access to a flag from the waiting thread and the thread doing the work. If you abort, you write from the waiting thread, and then the threads doing work check the flag periodically to see if it should stop work. The Task Parallel library (the Task class) in .NET 4.0 has a lot of this built in for you, so I suggest you look to that, if possible.
casperOne
@casperOne: Thanks, I'll give your suggestion a try.
BeckyLou