C# Set method timeout using Generics
I’m pretty sure all of you know the WebRequest and it’s derived class HttpWebRequest.
And what a marvelous property both of them have – the TimeOut.
Yesterday I had to write some app that reads files located on some remote computer.
As I knew already this ins’t such a good practice, because your code can just hang/freeze for seconds waiting for that UNC path to become available or just checking it’s existence.
Still, I had to provide some quick solution and “hoping for the best” wasn’t good enough.
So, this is what I came up with.
public static T Limex<T>(Func<T> F, int Timeout, out bool Completed)
{
T result = default(T);
Thread thread = new Thread(() => result = F());
thread.Start();
Completed = thread.Join(Timeout);
if (!Completed) thread.Abort();
return result;
}
// Overloaded method, for cases when we don't
// need to know if the method was terminated
public static T Limex<T>(Func<T> F, int Timeout)
{
bool Completed;
return Limex(F, Timeout, out Completed);
}
The usage is very simple, just pass any method (declared or anonymous) and the desired Timeout in milliseconds to the Limex.
Example :
bool Completed;
string Content = Limex(() => File.ReadAllText(@"\\unc\dir\file.ext")
,100 // milliseconds
,out Completed);
if (Completed)
// Do something
else
// Do something else
Comments and suggestions for improvement are welcome and will be gratefully appreciated
C# Set method timeout using Generics,

Line 15 in the code is wrong. It looks like you renamed LimitedExecute to LimEx but didn’t catch this instance of the method name.
@Joe Chung
Thanks, fixed it.
useful post ! a lot better than quizzes !
@Amr Ellafy
Thanks, your point is well taken.
Nice idea, but I think creating a new thread is a bit heavyweight, especially if the wrapped function needs to be called many times a second. Why not use the standard .Net async pattern? Something like this (untested):
public static T Limex(Func F, int Timeout, out bool Completed)
{
var iar = F.BeginInvoke(null, new object());
if (iar.AsyncWaitHandle.WaitOne(Timeout))
{
Completed = true;
return F.EndInvoke(iar);
}
Completed = false;
return default(T);
}
@Russ
Ok, but where do you abort the Func ? If you don’t it it will just continue running.
@Russ
BTW, as i recall BeginInvoke also creates a new thread, so…
Well, you’ve changed your code – when I wrote my reply there wasn’t a thread abort in there, so my alternative was equivalent.
Using Thread.Abort is regarded as a bad thing for a number of reasons. For a start, any function that you wrap this way that uses expensive resources or shared state will need to handle ThreadAbortException to make sure it leaves things in a sane state. On 64-bit systems, aborting a thread can cause resource leaks. In .Net 1.1, coding this way can even break a finally block. http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx
If you REALLY want an equivalent, however, you could rewrap F in an Action delegate that also captures Thread.CurrentThread, then abort that thread after a timeout. I wouldn’t recommend it though. If it’s that important that the wrapped function is killed, execute it in its own appdomain.
Also, BeginInvoke will use a threadpool thread, not a new thread. Therefore you don’t have the initialisation cost of creating a new thread, and you don’t suck up another meg of memory for thread stack space.
@Russ
You right, i accidentally deleted the .Abort() line while writing this post (my mistake) – without it this code would make no sense ( funny nobody noticed it ).
About the AppDomain – i thought about it, but isn’t it even heavier ?
In my case we are talking about thousands very short (50ms) operations.
Yes, in fairness an appdomain is even heavier.
@Russ
About the ThreadPool – it’s exactly what i don’t want. It’s supposed to be executed as a synchronous operation which won’t be possible using ThreadPool.
That’s why you use iar.AsyncWaitHandle.WaitOne(Timeout) – it blocks on the calling thread while the operation takes place on the threadpool thread. That’s equivalent to your Join call. It’s exactly analogous to your approach, it just doesn’t need to create a new thread.
@Russ
Ok, i agree that this is a much safer way, but correct me if i am wrong – your solution won’t allow to terminate the thread after the timeout and it will continue running without releasing the queue.
Let’s say you are executing some loop with 100ms timeout – you will get the result after 100ms (null or not), but the loop will continue executing till it stops (which is very bad and dangerous)
@Russ
Just to visualize my previous reply :
// This is your solution public static T SafeLimex<T>(Func<T> F, int Timeout, out bool Completed) { var iar = F.BeginInvoke(null, new object()); if (iar.AsyncWaitHandle.WaitOne(Timeout)) { Completed = true; return F.EndInvoke(iar); } Completed = false; return default(T); }Now let’s try to execute the next code :
for (int n = 0; n < 100; n++) { var r = SafeLimex(() => { Console.WriteLine("\n\rThread : " + Thread.CurrentThread.ManagedThreadId); Thread.Sleep(100); for (int i = 0; i < 1000; i++) { Console.Write(i); } return "result"; }, 120, out Finished); Console.WriteLine("\n\r" + "Result : " + r + ", Finished : " + Finished); }You will get something like this :
Thread : 7
0123456789101….454647484950…561
Result : , Finished : False
5625635645……………………………….601
Thread : 11
602603604…………………………………698
Result : , Finished : False
699……………………………………………999
As I said in my second comment, you can terminate if you capture the current thread, e.g.
Thread t = null;
Action action = () =>
{
t = Thread.CurrentThread;
F();
};
Then you call BeginInvoke on action instead of F. The action delegate will execute on the threadpool, so in that context Thread.CurrentThread will be your threadpool thread. If WaitOne returns false, you call t.Abort(). This is nasty for reasons I mentioned earlier, with the added problem that it gradually wrecks the threadpool.
I’m not necessarily arguing that my way is better, just an alternative. Fundamentally, there is no first-class language support for what you’re trying to do, so any solution is going to be hacky in some respect. If your solution is working for you, don’t sweat it – just be aware of the risks, particularly with Thread.Abort().
@Russ , I’ll be sure to check your solution in a runtime environment.
Thanks for a great discussion and i hope to see you in my future posts.
Don’t forget to eventually cleanup the async call:
private static T InvokeWithTimeout(Func operation)
{
T result = default(T);
if (timeout == 0)
{
result = operation.Invoke();
}
else
{
var async = operation.BeginInvoke(AsyncCleanup,operation);
if (async.AsyncWaitHandle.WaitOne(timeout))
{
result = operation.EndInvoke(async);
}
}
return result;
}
private static void AsyncCleanup(IAsyncResult result)
{
var operation = result.AsyncState as Func;
if (operation != null)
{
operation.EndInvoke(result);
}
}
i’m new… promise to post around more time after time!
What about for calling void methods?
Hi, David
You can overload it with something like this :
public static void Limex(Action A, int Timeout, out bool Completed)
{
Limex(new Func(() => { A(); return null; }), Timeout, out Completed);
}
and call it as following :
static void Test()
{
Thread.Sleep(5000);
}
Limex(Test, 100, out Completed);
Hi!
Very interesting name by the forum kossovsky.net
This situation is familiar to me. Is ready to help.
The possession of unlimited power will make a despot of almost any man.
Buy-buy!
Hi,
Thanks. This article is very useful.
I am getting compile time error for void return methods:
public static void Limex(Action A, int Timeout, out bool Completed)
{
Limex(new Func(() => { A(); return null; }), Timeout, out Completed);
}
I have added above function. Here Func is generating error. Below is the compile time error message:
Using the generic type ‘System.Func’ requires 10 type arguments
Am I doing anything wrong here?
Can you please look into this?
Thank you so much Xander. I was looking for the same kind of functionality and you saved my day. Let me try to implement it and see how it works. Thanks again.