I'm running parallel operations on a list of PCs I'm getting from the Active Directory. I was using this method to check PC states, such as whether the computer was online, or if a specific directory existed. However due to the nature of these, sometimes slow, operations, I wanted to include a timeout so my application could continue to operate.
public static T MethodTimeout<T>(Func<T> f, int timeout, out bool completed)
{
T result = default(T);
var thread = new Thread(() => result = F());
thread.Start();
Completed = thread.Join(Timeout);
if (!Completed) thread.Abort();
return result;
}
This works for the most part, but the processing usage seemed to spike a little, and in a few cases I ran into Out of Memory exceptions. So, I since changed the method to use tasks in the hope that the ThreadPool
would eliminate the aforementioned problems:
public static T MethodTimeout<T>(Func<T> f, int timeout, out bool completed)
{
T result = default(T);
var timedTask = Task.Factory.StartNew(() => result = F());
Completed = timedTask.Wait(Timeout);
return result;
}
However, I have a feeling I'm just filling up the ThreadPool
with processes that are hanging waiting for these potentially long tasks to finish. Since I'm passing the task's function as a parameter I don't see a way to use a cancellation token. However, my experience is very limited with these classes and I might be missing some superior techniques.
Here's how I've been using the method above:
bool isReachable; // Check if the directory exists (1 second)
MethodTimeout(() => Directory.Exists(startDirectory), 1000, out isReachable);
A quick note, I'm only running the above check after I've already confirmed the PC is online via a WMI call (also using MethodTimeout
). I'm aware through my early testing that checking the directory before that ends up being inefficient.
I'm also open to replacing this approach with something better.